1  /-
  2  Copyright (c) 2015 Microsoft Corporation. All rights reserved.
  3  Released under Apache 2.0 license as described in the file LICENSE.
  4  Author: Leonardo de Moura, Jeremy Avigad, Minchao Wu, Mario Carneiro
  5  
  6  Finite sets.
  7  -/
  8  import logic.embedding algebra.order_functions
src         └─────────────┘ └─────────────────────┘
  9    data.multiset data.sigma.basic data.set.lattice
src    └───────────┘ └──────────────┘ └──────────────┘
 10  
 11  open multiset subtype nat lattice
 12  
 13  variables {α : Type*} {β : Type*} {γ : Type*}
id             
typ            
 14  
 15  /-- `finset α` is the type of finite sets of elements of `α`. It is implemented
 16    as a multiset (a list up to permutation) which has no duplicate elements. -/
 17  structure finset (α : Type*) :=
id                         └───┘
typ                        └───┘
 18  (val : multiset α)
id          └──────┘ 
src         └──────┘
typ         └──────┘ 
doc         └──────┘
 19  (nodup : nodup val)
id            └───┘ └─┘
src           └───┘
typ           └───┘ └─┘
doc           └───┘
 20  
 21  namespace finset
 22  
 23  theorem eq_of_veq : ∀ {s t : finset α}, s.1 = t.1 → s = t
id                               └────┘             
src                               └────┘                
typ                              └────┘             
doc                               └────┘
 24  | ⟨s, _⟩ ⟨t, _⟩ rfl := rfl
id                   └─┘    └─┘
src                  └─┘    └─┘
typ                  └─┘    └─┘
 25  
 26  @[simp] theorem val_inj {s t : finset α} : s.1 = t.1 ↔ s = t :=
id                                  └────┘             
src                                 └────┘                
typ                                 └────┘             
doc    └──┘                         └────┘
 27  ⟨eq_of_veq, congr_arg _⟩
id    └───────┘  └───────┘
src   └───────┘  └───────┘
typ   └───────┘  └───────┘
 28  
 29  @[simp] theorem erase_dup_eq_self [decidable_eq α] (s : finset α) : erase_dup s.1 = s.1 :=
id                                      └──────────┘        └────┘     └───────┘    
src                                     └──────────┘         └────┘      └───────┘      
typ                                     └──────────┘        └────┘     └───────┘    
doc    └──┘                                                  └────┘      └───────┘
 30  erase_dup_eq_self.2 s.2
id   └───────────────┘  
src  └───────────────┘   
typ  └───────────────┘  
 31  
 32  instance has_decidable_eq [decidable_eq α] : decidable_eq (finset α)
id                              └──────────┘     └──────────┘  └────┘ 
src                             └──────────┘      └──────────┘  └────┘
typ                             └──────────┘     └──────────┘  └────┘ 
doc                                                             └────┘
 33  | s₁ s₂ := decidable_of_iff _ val_inj
id              └──────────────┘   └─────┘
src             └──────────────┘   └─────┘
typ             └──────────────┘   └─────┘
 34  
 35  /- membership -/
 36  
 37  instance : has_mem α (finset α) := ⟨λ a s, a ∈ s.1⟩
id              └─────┘   └────┘              
src             └─────┘    └────┘                   
typ             └─────┘   └────┘              
doc                        └────┘
 38  
 39  theorem mem_def {a : α} {s : finset α} : a ∈ s ↔ a ∈ s.1 := iff.rfl
id                               └────┘                └─────┘
src                               └────┘                     └─────┘
typ                              └────┘                └─────┘
doc                               └────┘
 40  
 41  @[simp] theorem mem_mk {a : α} {s nd} : a ∈ @finset.mk α s nd ↔ a ∈ s := iff.rfl
id                                             └───────┘   └┘        └─────┘
src                                              └───────┘                 └─────┘
typ                                            └───────┘   └┘        └─────┘
doc    └──┘
 42  
 43  instance decidable_mem [h : decidable_eq α] (a : α) (s : finset α) : decidable (a ∈ s) :=
id                               └──────────┘               └────┘     └───────┘    
src                              └──────────┘                 └────┘      └───────┘    
typ                              └──────────┘               └────┘     └───────┘    
doc                                                           └────┘
 44  multiset.decidable_mem _ _
id   └────────────────────┘
src  └────────────────────┘
typ  └────────────────────┘
 45  
 46  /-! ### set coercion -/
 47  
 48  /-- Convert a finset to a set in the natural way. -/
 49  def to_set (s : finset α) : set α := {x | x ∈ s}
id                   └────┘     └─┘          
src                  └────┘      └─┘            
typ                  └────┘     └─┘          
doc                  └────┘
 50  
 51  instance : has_lift (finset α) (set α) := ⟨to_set⟩
id              └──────┘  └────┘    └─┘       └────┘
src             └──────┘  └────┘     └─┘        └────┘
typ             └──────┘  └────┘    └─┘       └────┘
doc                       └────┘                └────┘
 52  
 53  @[simp] lemma mem_coe {a : α} {s : finset α} : a ∈ (↑s : set α) ↔ a ∈ s := iff.rfl
id                                     └────┘           └─┘          └─────┘
src                                     └────┘              └─┘             └─────┘
typ                                    └────┘           └─┘          └─────┘
doc    └──┘                             └────┘
 54  
 55  @[simp] lemma set_of_mem {α} {s : finset α} : {a | a ∈ s} = ↑s := rfl
id                                     └────┘                 └─┘
src                                    └────┘                      └─┘
typ                                    └────┘                 └─┘
doc    └──┘                            └────┘
 56  
 57  instance decidable_mem' [decidable_eq α] (a : α) (s : finset α) :
id                            └──────────┘               └────┘ 
src                           └──────────┘                 └────┘
typ                           └──────────┘               └────┘ 
doc                                                        └────┘
 58    decidable (a ∈ (↑s : set α)) := s.decidable_mem _
id     └───────┘        └─┘       └────────────┘
src    └───────┘          └─┘         └────────────┘
typ    └───────┘        └─┘       └────────────┘
 59  
 60  /-! ### extensionality -/
 61  theorem ext {s₁ s₂ : finset α} : s₁ = s₂ ↔ ∀ a, a ∈ s₁ ↔ a ∈ s₂ :=
id                        └────┘     └┘  └┘        └┘    └┘
src                       └────┘                            
typ                       └────┘     └┘  └┘        └┘    └┘
doc                       └────┘
 62  val_inj.symm.trans $ nodup_ext s₁.2 s₂.2
id   └─────┘└───┘└────┘   └───────┘ └┘  └┘
src  └─────┘└───┘└────┘   └───────┘       
typ  └─────┘└───┘└────┘   └───────┘ └┘  └┘
 63  
 64  @[ext]
doc    └─┘
 65  theorem ext' {s₁ s₂ : finset α} : (∀ a, a ∈ s₁ ↔ a ∈ s₂) → s₁ = s₂ :=
id                         └────┘            └┘    └┘    └┘  └┘
src                        └────┘                               
typ                        └────┘            └┘    └┘    └┘  └┘
doc                        └────┘
 66  ext.2
id   └─┘
src  └─┘
typ  └─┘
 67  
 68  @[simp] theorem coe_inj {s₁ s₂ : finset α} : (↑s₁ : set α) = ↑s₂ ↔ s₁ = s₂ :=
id                                    └────┘      └┘   └─┘    └┘  └┘  └┘
src                                   └────┘            └─┘            
typ                                   └────┘      └┘   └─┘    └┘  └┘  └┘
doc    └──┘                           └────┘
 69  (set.ext_iff _ _).trans ext.symm
id    └─────────┘     └───┘  └─┘└───┘
src   └─────────┘     └───┘  └─┘└───┘
typ   └─────────┘     └───┘  └─┘└───┘
 70  
 71  lemma to_set_injective {α} : function.injective (finset.to_set : finset α → set α) :=
id                                └────────────────┘  └───────────┘   └────┘    └─┘ 
src                               └────────────────┘  └───────────┘   └────┘     └─┘
typ                               └────────────────┘  └───────────┘   └────┘    └─┘ 
doc                                                   └───────────┘   └────┘
 72  λ s t, coe_inj.1
id        └─────┘
src         └─────┘
typ       └─────┘
 73  
 74  /-! ### subset -/
 75  
 76  instance : has_subset (finset α) := ⟨λ s₁ s₂, ∀ ⦃a⦄, a ∈ s₁ → a ∈ s₂⟩
id              └────────┘  └────┘         └┘ └┘          └┘     └┘
src             └────────┘  └────┘                                  
typ             └────────┘  └────┘         └┘ └┘          └┘     └┘
doc                         └────┘
 77  
 78  theorem subset_def {s₁ s₂ : finset α} : s₁ ⊆ s₂ ↔ s₁.1 ⊆ s₂.1 := iff.rfl
id                               └────┘     └┘  └┘  └┘   └┘     └─────┘
src                              └────┘                          └─────┘
typ                              └────┘     └┘  └┘  └┘   └┘     └─────┘
doc                              └────┘
 79  
 80  @[simp] theorem subset.refl (s : finset α) : s ⊆ s := subset.refl _
id                                    └────┘           └─────────┘
src                                   └────┘              └─────────┘
typ                                   └────┘           └─────────┘
doc    └──┘                           └────┘
 81  
 82  theorem subset.trans {s₁ s₂ s₃ : finset α} : s₁ ⊆ s₂ → s₂ ⊆ s₃ → s₁ ⊆ s₃ := subset.trans
id                                    └────┘     └┘  └┘   └┘  └┘   └┘  └┘    └──────────┘
src                                   └────┘                                  └──────────┘
typ                                   └────┘     └┘  └┘   └┘  └┘   └┘  └┘    └──────────┘
doc                                   └────┘
 83  
 84  theorem mem_of_subset {s₁ s₂ : finset α} {a : α} : s₁ ⊆ s₂ → a ∈ s₁ → a ∈ s₂ := mem_of_subset
id                                  └────┘            └┘  └┘     └┘     └┘    └───────────┘
src                                 └────┘                                        └───────────┘
typ                                 └────┘            └┘  └┘     └┘     └┘    └───────────┘
doc                                 └────┘
 85  
 86  theorem subset.antisymm {s₁ s₂ : finset α} (H₁ : s₁ ⊆ s₂) (H₂ : s₂ ⊆ s₁) : s₁ = s₂ :=
id                                    └────┘         └┘  └┘        └┘  └┘    └┘  └┘
src                                   └────┘                                     
typ                                   └────┘         └┘  └┘        └┘  └┘    └┘  └┘
doc                                   └────┘
 87  ext.2 $ λ a, ⟨@H₁ a, @H₂ a⟩
id   └─┘          └┘    └┘ 
src  └─┘
typ  └─┘          └┘    └┘ 
 88  
 89  theorem subset_iff {s₁ s₂ : finset α} : s₁ ⊆ s₂ ↔ ∀ ⦃x⦄, x ∈ s₁ → x ∈ s₂ := iff.rfl
id                               └────┘     └┘  └┘          └┘     └┘    └─────┘
src                              └────┘                                      └─────┘
typ                              └────┘     └┘  └┘          └┘     └┘    └─────┘
doc                              └────┘
 90  
 91  @[simp] theorem coe_subset {s₁ s₂ : finset α} :
id                                       └────┘ 
src                                      └────┘
typ                                      └────┘ 
doc    └──┘                              └────┘
 92    (↑s₁ : set α) ⊆ ↑s₂ ↔ s₁ ⊆ s₂ := iff.rfl
id      └┘   └─┘    └┘  └┘  └┘    └─────┘
src          └─┘                   └─────┘
typ     └┘   └─┘    └┘  └┘  └┘    └─────┘
 93  
 94  @[simp] theorem val_le_iff {s₁ s₂ : finset α} : s₁.1 ≤ s₂.1 ↔ s₁ ⊆ s₂ := le_iff_subset s₁.2
id                                       └────┘     └┘   └┘   └┘  └┘    └───────────┘ └┘
src                                      └────┘                          └───────────┘   
typ                                      └────┘     └┘   └┘   └┘  └┘    └───────────┘ └┘
doc    └──┘                              └────┘
 95  
 96  instance : has_ssubset (finset α) := ⟨λa b, a ⊆ b ∧ ¬ b ⊆ a⟩
id              └─────────┘  └────┘                  
src             └─────────┘  └────┘                       
typ             └─────────┘  └────┘                  
doc                          └────┘
 97  
 98  instance : partial_order (finset α) :=
id              └───────────┘  └────┘ 
src             └───────────┘  └────┘
typ             └───────────┘  └────┘ 
doc                            └────┘
 99  { le := (⊆),
id          
src         
typ         
100    lt := (⊂),
id           
src          
typ          
101    le_refl := subset.refl,
id                └─────────┘
src               └─────────┘
typ               └─────────┘
102    le_trans := @subset.trans _,
id                  └──────────┘
src                 └──────────┘
typ                 └──────────┘
103    le_antisymm := @subset.antisymm _ }
id                     └─────────────┘
src                    └─────────────┘
typ                    └─────────────┘
104  
105  theorem subset.antisymm_iff {s₁ s₂ : finset α} : s₁ = s₂ ↔ s₁ ⊆ s₂ ∧ s₂ ⊆ s₁ :=
id                                        └────┘     └┘  └┘  └┘  └┘  └┘  └┘
src                                       └────┘                         
typ                                       └────┘     └┘  └┘  └┘  └┘  └┘  └┘
doc                                       └────┘
106  le_antisymm_iff
id   └─────────────┘
src  └─────────────┘
typ  └─────────────┘
107  
108  @[simp] theorem le_iff_subset {s₁ s₂ : finset α} : s₁ ≤ s₂ ↔ s₁ ⊆ s₂ := iff.rfl
id                                          └────┘     └┘  └┘  └┘  └┘    └─────┘
src                                         └────┘                        └─────┘
typ                                         └────┘     └┘  └┘  └┘  └┘    └─────┘
doc    └──┘                                 └────┘
109  @[simp] theorem lt_iff_ssubset {s₁ s₂ : finset α} : s₁ < s₂ ↔ s₁ ⊂ s₂ := iff.rfl
id                                           └────┘     └┘  └┘  └┘  └┘    └─────┘
src                                          └────┘                        └─────┘
typ                                          └────┘     └┘  └┘  └┘  └┘    └─────┘
doc    └──┘                                  └────┘
110  
111  @[simp] lemma coe_ssubset {s₁ s₂ : finset α} : (↑s₁ : set α) ⊂ ↑s₂ ↔ s₁ ⊂ s₂ :=
id                                      └────┘      └┘   └─┘    └┘  └┘  └┘
src                                     └────┘            └─┘            
typ                                     └────┘      └┘   └─┘    └┘  └┘  └┘
doc    └──┘                             └────┘
112  show (↑s₁ : set α) ⊂ ↑s₂ ↔ s₁ ⊆ s₂ ∧ ¬s₂ ⊆ s₁,
id         └┘   └─┘    └┘  └┘  └┘  └┘  └┘
src             └─┘                    
typ        └┘   └─┘    └┘  └┘  └┘  └┘  └┘
113    by simp only [set.ssubset_def, finset.coe_subset]
id                   └─────────────┘  └───────────────┘
src       └─────────┘└─────────────┘└┘└───────────────┘└─
typ       └─────────┘└─────────────┘└┘└───────────────┘└─
doc       └─────────┘               └┘                 └─
txt       └─────────┘               └┘                 └─
par       └─────────┘               └┘                 └─
pid           └──┘└┘               └┘                 
st       └───────────────────────────────────────────────
114  
src  
typ  
doc  
txt  
par  
pid  
st   
115  @[simp] theorem val_lt_iff {s₁ s₂ : finset α} : s₁.1 < s₂.1 ↔ s₁ ⊂ s₂ :=
id                                       └────┘     └┘   └┘   └┘  └┘
src                                      └────┘                   
typ                                      └────┘     └┘   └┘   └┘  └┘
doc    └──┘                              └────┘
116  and_congr val_le_iff $ not_congr val_le_iff
id   └───────┘ └────────┘   └───────┘ └────────┘
src  └───────┘ └────────┘   └───────┘ └────────┘
typ  └───────┘ └────────┘   └───────┘ └────────┘
117  
118  /-! ### Nonempty -/
119  
120  /-- The property `s.nonempty` expresses the fact that the finset `s` is not empty. It should be used
121  in theorem assumptions instead of `∃ x, x ∈ s` or `s ≠ ∅` as it gives access to a nice API thanks
122  to the dot notation. -/
123  protected def nonempty (s : finset α) : Prop := ∃ x:α, x ∈ s
id                               └────┘                   
src                              └────┘                     
typ                              └────┘                   
doc                              └────┘
124  
125  @[elim_cast] lemma coe_nonempty {s : finset α} : (↑s:set α).nonempty ↔ s.nonempty := iff.rfl
id                                        └────┘       └─┘  └──────┘   └───────┘    └─────┘
src                                       └────┘         └─┘   └──────┘    └───────┘    └─────┘
typ                                       └────┘       └─┘  └──────┘   └───────┘    └─────┘
doc    └───────┘                          └────┘                └──────┘     └───────┘
126  
127  lemma nonempty.bex {s : finset α} (h : s.nonempty) : ∃ x:α, x ∈ s := h
id                           └────┘        └───────┘              
src                          └────┘          └───────┘           
typ                          └────┘        └───────┘              
doc                          └────┘          └───────┘
128  
129  lemma nonempty.mono {s t : finset α} (hst : s ⊆ t) (hs : s.nonempty) : t.nonempty :=
id                              └────┘                    └───────┘    └───────┘
src                             └────┘                        └───────┘     └───────┘
typ                             └────┘                    └───────┘    └───────┘
doc                             └────┘                         └───────┘     └───────┘
130  set.nonempty.mono hst hs
id   └───────────────┘ └─┘ └┘
src  └───────────────┘
typ  └───────────────┘ └─┘ └┘
131  
132  /-! ### empty -/
133  protected def empty : finset α := ⟨0, nodup_zero⟩
id                         └────┘         └────────┘
src                        └────┘          └────────┘
typ                        └────┘         └────────┘
doc                        └────┘
134  
135  instance : has_emptyc (finset α) := ⟨finset.empty⟩
id              └────────┘  └────┘       └──────────┘
src             └────────┘  └────┘        └──────────┘
typ             └────────┘  └────┘       └──────────┘
doc                         └────┘
st                                                     
136  
137  instance : inhabited (finset α) := ⟨∅⟩
id              └───────┘  └────┘       
src             └───────┘  └────┘        
typ             └───────┘  └────┘       
doc                        └────┘
138  
139  @[simp] theorem empty_val : (∅ : finset α).1 = 0 := rfl
id                                   └────┘          └─┘
src                                  └────┘           └─┘
typ                                  └────┘          └─┘
doc    └──┘                           └────┘
140  
141  @[simp] theorem not_mem_empty (a : α) : a ∉ (∅ : finset α) := id
id                                                └────┘      └┘
src                                                 └────┘       └┘
typ                                               └────┘      └┘
doc    └──┘                                           └────┘
142  
143  @[simp] theorem ne_empty_of_mem {a : α} {s : finset α} (h : a ∈ s) : s ≠ ∅
id                                               └────┘                
src                                               └────┘                    
typ                                              └────┘                
doc    └──┘                                       └────┘
144  | e := not_mem_empty a $ e ▸ h
id         └───────────┘       
src         └───────────┘       
typ        └───────────┘       
145  
146  @[simp] theorem empty_subset (s : finset α) : ∅ ⊆ s := zero_subset _
id                                     └────┘           └─────────┘
src                                    └────┘             └─────────┘
typ                                    └────┘           └─────────┘
doc    └──┘                            └────┘
147  
148  theorem eq_empty_of_forall_not_mem {s : finset α} (H : ∀x, x ∉ s) : s = ∅ :=
id                                           └────┘                   
src                                          └────┘                        
typ                                          └────┘                   
doc                                          └────┘
149  eq_of_veq (eq_zero_of_forall_not_mem H)
id   └───────┘  └───────────────────────┘ 
src  └───────┘  └───────────────────────┘
typ  └───────┘  └───────────────────────┘ 
150  
151  lemma eq_empty_iff_forall_not_mem {s : finset α} : s = ∅ ↔ ∀ x, x ∉ s :=
id                                          └────┘               
src                                         └────┘                  
typ                                         └────┘               
doc                                         └────┘
152  ⟨by rintro rfl x; exact id, λ h, eq_empty_of_forall_not_mem h⟩
id                           └┘      └────────────────────────┘ 
src      └──────────┘  └────┘└┘       └────────────────────────┘
typ      └──────────┘  └────┘└┘      └────────────────────────┘ 
doc      └──────────┘  └────┘
txt      └──────────┘  └────┘
par      └──────────┘  └────┘
pid            └────┘       
st      └─────────────────────┘
153  
154  @[simp] theorem val_eq_zero {s : finset α} : s.1 = 0 ↔ s = ∅ := @val_inj _ s ∅
id                                    └────┘                  └─────┘    
src                                   └────┘                     └─────┘     
typ                                   └────┘                  └─────┘    
doc    └──┘                           └────┘
155  
156  theorem subset_empty {s : finset α} : s ⊆ ∅ ↔ s = ∅ := subset_zero.trans val_eq_zero
id                             └────┘               └─────────┘└────┘ └─────────┘
src                            └────┘                  └─────────┘└────┘ └─────────┘
typ                            └────┘               └─────────┘└────┘ └─────────┘
doc                            └────┘
157  
158  theorem nonempty_of_ne_empty {s : finset α} (h : s ≠ ∅) : s.nonempty :=
id                                     └────┘              └───────┘
src                                    └────┘                 └───────┘
typ                                    └────┘              └───────┘
doc                                    └────┘                   └───────┘
159  exists_mem_of_ne_zero (mt val_eq_zero.1 h)
id   └───────────────────┘  └┘ └─────────┘  
src  └───────────────────┘  └┘ └─────────┘
typ  └───────────────────┘  └┘ └─────────┘  
160  
161  theorem nonempty_iff_ne_empty {s : finset α} : s.nonempty ↔ s ≠ ∅ :=
id                                      └────┘     └───────┘    
src                                     └────┘       └───────┘     
typ                                     └────┘     └───────┘    
doc                                     └────┘       └───────┘
162  ⟨λ ⟨a, ha⟩, ne_empty_of_mem ha, nonempty_of_ne_empty⟩
id         └┘   └─────────────┘     └──────────────────┘
src              └─────────────┘     └──────────────────┘
typ        └┘   └─────────────┘     └──────────────────┘
163  
164  theorem eq_empty_or_nonempty (s : finset α) : s = ∅ ∨ s.nonempty :=
id                                     └────┘         └───────┘
src                                    └────┘            └───────┘
typ                                    └────┘         └───────┘
doc                                    └────┘               └───────┘
165  classical.by_cases or.inl (λ h, or.inr (nonempty_of_ne_empty h))
id   └────────────────┘ └────┘      └────┘  └──────────────────┘ 
src  └────────────────┘ └────┘       └────┘  └──────────────────┘
typ  └────────────────┘ └────┘      └────┘  └──────────────────┘ 
166  
167  @[simp] lemma coe_empty : ↑(∅ : finset α) = (∅ : set α) := rfl
id                                 └────┘        └─┘      └─┘
src                                └────┘         └─┘       └─┘
typ                                └────┘        └─┘      └─┘
doc    └──┘                          └────┘
168  
169  /-- `singleton a` is the set `{a}` containing `a` and nothing else. -/
170  def singleton (a : α) : finset α := ⟨_, nodup_singleton a⟩
id                          └────┘         └─────────────┘ 
src                          └────┘          └─────────────┘
typ                         └────┘         └─────────────┘ 
doc                          └────┘
171  local prefix `ι`:90 := singleton
id                          └───────┘
src                         └───────┘
typ                         └───────┘
doc                         └───────┘
172  
173  @[simp] theorem singleton_val (a : α) : (ι a).1 = a :: 0 := rfl
id                                                 └┘      └─┘
src                                                   └┘      └─┘
typ                                                └┘      └─┘
doc    └──┘                                             └┘
174  
175  @[simp] theorem mem_singleton {a b : α} : b ∈ ι a ↔ b = a := mem_singleton
id                                                       └───────────┘
src                                                           └───────────┘
typ                                                      └───────────┘
doc    └──┘                                        
176  
177  theorem not_mem_singleton {a b : α} : a ∉ ι b ↔ a ≠ b := not_iff_not_of_iff mem_singleton
id                                                   └────────────────┘ └───────────┘
src                                                       └────────────────┘ └───────────┘
typ                                                  └────────────────┘ └───────────┘
doc                                            
178  
179  theorem mem_singleton_self (a : α) : a ∈ ι a := or.inl rfl
id                                              └────┘ └─┘
src                                                └────┘ └─┘
typ                                             └────┘ └─┘
doc                                           
180  
181  theorem singleton_inj {a b : α} : ι a = ι b ↔ a = b :=
id                                            
src                                              
typ                                           
doc                                         
182  ⟨λ h, mem_singleton.1 (h ▸ mem_singleton_self _), congr_arg _⟩
id        └───────────┘     └────────────────┘     └───────┘
src        └───────────┘      └────────────────┘     └───────┘
typ       └───────────┘     └────────────────┘     └───────┘
183  
184  @[simp] theorem singleton_ne_empty (a : α) : ι a ≠ ∅ := ne_empty_of_mem (mem_singleton_self _)
id                                                      └─────────────┘  └────────────────┘
src                                                       └─────────────┘  └────────────────┘
typ                                                     └─────────────┘  └────────────────┘
doc    └──┘                                       
185  
186  @[simp] lemma coe_singleton (a : α) : ↑(ι a) = ({a} : set α) := rfl
id                                                  └─┘      └─┘
src                                                    └─┘       └─┘
typ                                                 └─┘      └─┘
doc    └──┘                                  
187  
188  lemma eq_singleton_iff_unique_mem {s : finset α} {a : α} :
id                                          └────┘        
src                                         └────┘
typ                                         └────┘        
doc                                         └────┘
189    s = finset.singleton a ↔ a ∈ s ∧ ∀ x ∈ s, x = a :=
id       └──────────────┘                
src       └──────────────┘                    
typ      └──────────────┘                
doc        └──────────────┘
190  begin
st   └─────
191    split; intro t,
src    └───┘  └─────┘
typ    └───┘  └─────┘
doc    └───┘  └─────┘
txt    └───┘  └─────┘
par    └───┘  └─────┘
pid                └┘
st   ───────────────┘└─
192      rw t,
id          
src      └─┘
typ      └─┘
doc      └─┘
txt      └─┘
par      └─┘
pid        
st   ───────┘└─
193      refine ⟨finset.mem_singleton_self _, λ _, finset.mem_singleton.1⟩,
id               └───────────────────────┘         └──────────────────┘
src      └─────┘ └───────────────────────┘└──┘ └──┘└──────────────────┘└─┘
typ      └─────┘ └───────────────────────┘└──┘ └──┘└──────────────────┘└─┘
doc      └─────┘                          └──┘ └──┘                    └─┘
txt      └─────┘                          └──┘ └──┘                    └─┘
par      └─────┘                          └──┘ └──┘                    └─┘
pid                                      └──┘ └──┘                    └─┘
st   ────────────────────────────────────────────────────────────────────┘└─
194    ext, rw finset.mem_singleton,
id             └──────────────────┘
src    └─┘  └─┘└──────────────────┘
typ    └─┘  └─┘└──────────────────┘
doc    └─┘  └─┘
txt    └─┘  └─┘
par    └─┘  └─┘
pid           
st   ────┘└───────────────────────┘└─
195    refine ⟨t.right _, λ r, r.symm ▸ t.left⟩
id             └─────┘          └───┘  └────┘
src    └─────┘ └─────┘└──┘ └──┘ └───┘└────┘└┘
typ    └─────┘ └─────┘└──┘ └──┘ └───┘└────┘└┘
doc    └─────┘        └──┘ └──┘             └┘
txt    └─────┘        └──┘ └──┘             └┘
par    └─────┘        └──┘ └──┘             └┘
pid                  └──┘ └──┘             
st   ──────────────────────────────────────────┘
196  end
st   └─┘
197  
198  lemma singleton_iff_unique_mem (s : finset α) : (∃ a, s = finset.singleton a) ↔ ∃! a, a ∈ s :=
id                                       └────┘          └──────────────┘    └┘    
src                                      └────┘             └──────────────┘     └┘     
typ                                      └────┘          └──────────────┘    └┘    
doc                                      └────┘                └──────────────┘
199  by simp only [eq_singleton_iff_unique_mem, exists_unique]
id                 └─────────────────────────┘  └───────────┘
src     └─────────┘└─────────────────────────┘└┘└───────────┘└─
typ     └─────────┘└─────────────────────────┘└┘└───────────┘└─
doc     └─────────┘                           └┘             └─
txt     └─────────┘                           └┘             └─
par     └─────────┘                           └┘             └─
pid         └──┘└┘                           └┘             
st     └───────────────────────────────────────────────────────
200  
src  
typ  
doc  
txt  
par  
pid  
st   
201  /-! ### insert -/
202  section decidable_eq
203  variables [decidable_eq α]
id              └──────────┘
src             └──────────┘
typ             └──────────┘
204  
205  /-- `insert a s` is the set `{a} ∪ s` containing `a` and the elements of `s`. -/
206  instance : has_insert α (finset α) := ⟨λ a s, ⟨_, nodup_ndinsert a s.2⟩⟩
id              └────────┘   └────┘                └────────────┘  
src             └────────┘    └────┘                   └────────────┘    
typ             └────────┘   └────┘                └────────────┘  
doc                           └────┘
207  
208  @[simp] theorem has_insert_eq_insert (a : α) (s : finset α) : has_insert.insert a s = insert a s := rfl
id                                                    └────┘     └───────────────┘    └────┘      └─┘
src                                                    └────┘      └───────────────┘      └────┘        └─┘
typ                                                   └────┘     └───────────────┘    └────┘      └─┘
doc    └──┘                                            └────┘
209  
210  theorem insert_def (a : α) (s : finset α) : insert a s = ⟨_, nodup_ndinsert a s.2⟩ := rfl
id                                  └────┘     └────┘        └────────────┘        └─┘
src                                  └────┘      └────┘          └────────────┘          └─┘
typ                                 └────┘     └────┘        └────────────┘        └─┘
doc                                  └────┘
211  
212  @[simp] theorem insert_val (a : α) (s : finset α) : (insert a s).1 = ndinsert a s.1 := rfl
id                                          └────┘      └────┘      └──────┘       └─┘
src                                          └────┘       └────┘        └──────┘         └─┘
typ                                         └────┘      └────┘      └──────┘       └─┘
doc    └──┘                                  └────┘                       └──────┘
213  
214  theorem insert_val' (a : α) (s : finset α) : (insert a s).1 = erase_dup (a :: s.1) :=
id                                   └────┘      └────┘      └───────┘   └┘ 
src                                   └────┘       └────┘        └───────┘    └┘  
typ                                  └────┘      └────┘      └───────┘   └┘ 
doc                                   └────┘                       └───────┘    └┘
215  by rw [erase_dup_cons, erase_dup_eq_self]; refl
id          └────────────┘  └───────────────┘
src     └──┘└────────────┘└┘└───────────────┘  └────
typ     └──┘└────────────┘└┘└───────────────┘  └────
doc     └──┘              └┘                   └────
txt     └──┘              └┘                   └────
par     └──┘              └┘                   └────
pid       └┘              └┘                       
st     └─────────────────┘└─────────────────┘└──────
216  
src  
typ  
doc  
txt  
par  
pid  
st   
217  theorem insert_val_of_not_mem {a : α} {s : finset α} (h : a ∉ s) : (insert a s).1 = a :: s.1 :=
id                                             └────┘               └────┘       └┘ 
src                                             └────┘                  └────┘          └┘  
typ                                            └────┘               └────┘       └┘ 
doc                                             └────┘                                     └┘
218  by rw [insert_val, ndinsert_of_not_mem h]
id          └────────┘  └─────────────────┘ 
src     └──┘└────────┘└┘└─────────────────┘ └─
typ     └──┘└────────┘└┘└─────────────────┘└─
doc     └──┘          └┘                    └─
txt     └──┘          └┘                    └─
par     └──┘          └┘                    └─
pid       └┘          └┘                    
st     └─────────────┘└─────────────────────┘
219  
src  
typ  
doc  
txt  
par  
pid  
st   
220  @[simp] theorem mem_insert {a b : α} {s : finset α} : a ∈ insert b s ↔ a = b ∨ a ∈ s := mem_ndinsert
id                                            └────┘       └────┘              └──────────┘
src                                            └────┘         └────┘                    └──────────┘
typ                                           └────┘       └────┘              └──────────┘
doc    └──┘                                    └────┘
221  
222  theorem mem_insert_self (a : α) (s : finset α) : a ∈ insert a s := mem_ndinsert_self a s.1
id                                       └────┘       └────┘      └───────────────┘  
src                                       └────┘         └────┘        └───────────────┘    
typ                                      └────┘       └────┘      └───────────────┘  
doc                                       └────┘
223  theorem mem_insert_of_mem {a b : α} {s : finset α} (h : a ∈ s) : a ∈ insert b s := mem_ndinsert_of_mem h
id                                           └────┘                └────┘      └─────────────────┘ 
src                                           └────┘                    └────┘        └─────────────────┘
typ                                          └────┘                └────┘      └─────────────────┘ 
doc                                           └────┘
224  theorem mem_of_mem_insert_of_ne {a b : α} {s : finset α} (h : b ∈ insert a s) : b ≠ a → b ∈ s :=
id                                                 └────┘          └────┘             
src                                                 └────┘            └────┘                 
typ                                                └────┘          └────┘             
doc                                                 └────┘
225  (mem_insert.1 h).resolve_left
id    └────────┘   └──────────┘
src   └────────┘    └──────────┘
typ   └────────┘   └──────────┘
226  
227  @[simp] lemma coe_insert (a : α) (s : finset α) : ↑(insert a s) = (insert a ↑s : set α) :=
id                                        └────┘      └────┘      └────┘     └─┘ 
src                                        └────┘       └────┘        └────┘       └─┘
typ                                       └────┘      └────┘      └────┘     └─┘ 
doc    └──┘                                └────┘
228  set.ext $ λ x, by simp only [mem_coe, mem_insert, set.mem_insert_iff]
id   └─────┘                     └─────┘  └────────┘  └────────────────┘
src  └─────┘           └─────────┘└─────┘└┘└────────┘└┘└────────────────┘└─
typ  └─────┘          └─────────┘└─────┘└┘└────────┘└┘└────────────────┘└─
doc                    └─────────┘       └┘          └┘                  └─
txt                    └─────────┘       └┘          └┘                  └─
par                    └─────────┘       └┘          └┘                  └─
pid                        └──┘└┘       └┘          └┘                  
st                    └────────────────────────────────────────────────────
229  
src  
typ  
doc  
txt  
par  
pid  
st   
230  @[simp] theorem insert_eq_of_mem {a : α} {s : finset α} (h : a ∈ s) : insert a s = s :=
id                                                └────┘              └────┘    
src                                                └────┘                 └────┘     
typ                                               └────┘              └────┘    
doc    └──┘                                        └────┘
231  eq_of_veq $ ndinsert_of_mem h
id   └───────┘   └─────────────┘ 
src  └───────┘   └─────────────┘
typ  └───────┘   └─────────────┘ 
232  
233  theorem insert.comm (a b : α) (s : finset α) : insert a (insert b s) = insert b (insert a s) :=
id                                     └────┘     └────┘   └────┘     └────┘   └────┘  
src                                     └────┘      └────┘    └────┘       └────┘    └────┘
typ                                    └────┘     └────┘   └────┘     └────┘   └────┘  
doc                                     └────┘
234  ext.2 $ λ x, by simp only [finset.mem_insert, or.left_comm]
id   └─┘                      └───────────────┘  └──────────┘
src  └─┘            └─────────┘└───────────────┘└┘└──────────┘└─
typ  └─┘           └─────────┘└───────────────┘└┘└──────────┘└─
doc                  └─────────┘                 └┘            └─
txt                  └─────────┘                 └┘            └─
par                  └─────────┘                 └┘            └─
pid                      └──┘└┘                 └┘            
st                  └────────────────────────────────────────────
235  
src  
typ  
doc  
txt  
par  
pid  
st   
236  @[simp] theorem insert_idem (a : α) (s : finset α) : insert a (insert a s) = insert a s :=
id                                           └────┘     └────┘   └────┘     └────┘  
src                                           └────┘      └────┘    └────┘       └────┘
typ                                          └────┘     └────┘   └────┘     └────┘  
doc    └──┘                                   └────┘
237  ext.2 $ λ x, by simp only [finset.mem_insert, or.assoc.symm, or_self]
id   └─┘                      └───────────────┘                 └─────┘
src  └─┘            └─────────┘└───────────────┘└┘             └┘└─────┘└─
typ  └─┘           └─────────┘└───────────────┘└┘└───────────┘└┘└─────┘└─
doc                  └─────────┘                 └┘             └┘       └─
txt                  └─────────┘                 └┘             └┘       └─
par                  └─────────┘                 └┘             └┘       └─
pid                      └──┘└┘                 └┘             └┘       
st                  └──────────────────────────────────────────────────────
238  
src  
typ  
doc  
txt  
par  
pid  
st   
239  @[simp] theorem insert_ne_empty (a : α) (s : finset α) : insert a s ≠ ∅ :=
id                                               └────┘     └────┘    
src                                               └────┘      └────┘      
typ                                              └────┘     └────┘    
doc    └──┘                                       └────┘
240  ne_empty_of_mem (mem_insert_self a s)
id   └─────────────┘  └─────────────┘  
src  └─────────────┘  └─────────────┘
typ  └─────────────┘  └─────────────┘  
241  
242  lemma ne_insert_of_not_mem (s t : finset α) {a : α} (h : a ∉ s) :
id                                     └────┘                 
src                                    └────┘                   
typ                                    └────┘                 
doc                                    └────┘
243    s ≠ insert a t :=
id       └────┘  
src       └────┘
typ      └────┘  
244  by { contrapose! h, simp [h] }
id                             
src       └───────────┘  └────┘ └┘
typ       └───────────┘  └────┘└┘
doc       └───────────┘  └────┘ └┘
txt       └───────────┘  └────┘ └┘
par       └───────────┘  └────┘ └┘
pid                 └┘       
st     └──────────────┘└─────────┘└┘
245  
246  theorem insert_subset {a : α} {s t : finset α} : insert a s ⊆ t ↔ a ∈ t ∧ s ⊆ t :=
id                                       └────┘     └────┘            
src                                       └────┘      └────┘                 
typ                                      └────┘     └────┘            
doc                                       └────┘
247  by simp only [subset_iff, mem_insert, forall_eq, or_imp_distrib, forall_and_distrib]
id                 └────────┘  └────────┘  └───────┘  └────────────┘  └────────────────┘
src     └─────────┘└────────┘└┘└────────┘└┘└───────┘└┘└────────────┘└┘└────────────────┘└─
typ     └─────────┘└────────┘└┘└────────┘└┘└───────┘└┘└────────────┘└┘└────────────────┘└─
doc     └─────────┘          └┘          └┘         └┘              └┘                  └─
txt     └─────────┘          └┘          └┘         └┘              └┘                  └─
par     └─────────┘          └┘          └┘         └┘              └┘                  └─
pid         └──┘└┘          └┘          └┘         └┘              └┘                  
st     └──────────────────────────────────────────────────────────────────────────────────
248  
src  
typ  
doc  
txt  
par  
pid  
st   
249  theorem subset_insert (a : α) (s : finset α) : s ⊆ insert a s :=
id                                     └────┘       └────┘  
src                                     └────┘         └────┘
typ                                    └────┘       └────┘  
doc                                     └────┘
250  λ b, mem_insert_of_mem
id       └───────────────┘
src       └───────────────┘
typ      └───────────────┘
251  
252  theorem insert_subset_insert (a : α) {s t : finset α} (h : s ⊆ t) : insert a s ⊆ insert a t :=
id                                              └────┘              └────┘    └────┘  
src                                              └────┘                 └────┘      └────┘
typ                                             └────┘              └────┘    └────┘  
doc                                              └────┘
253  insert_subset.2 ⟨mem_insert_self _ _, subset.trans h (subset_insert _ _)⟩
id   └───────────┘   └─────────────┘      └──────────┘   └───────────┘
src  └───────────┘   └─────────────┘      └──────────┘    └───────────┘
typ  └───────────┘   └─────────────┘      └──────────┘   └───────────┘
254  
255  lemma ssubset_iff {s t : finset α} : s ⊂ t ↔ (∃a, a ∉ s ∧ insert a s ⊆ t) :=
id                            └────┘               └────┘    
src                           └────┘                     └────┘     
typ                           └────┘               └────┘    
doc                           └────┘
256  iff.intro
id   └───────┘
src  └───────┘
typ  └───────┘
257    (assume ⟨h₁, h₂⟩,
id             └┘
typ            └┘
258      have ∃a ∈ t, a ∉ s, by simpa only [finset.subset_iff, classical.not_forall] using h₂,
id                                   └───────────────┘  └──────────────────┘        └┘
src                          └──────────┘└───────────────┘└┘└──────────────────┘└──────┘
typ                      └──────────┘└───────────────┘└┘└──────────────────┘└──────┘└┘
doc                             └──────────┘                 └┘                    └──────┘
txt                             └──────────┘                 └┘                    └──────┘
par                             └──────────┘                 └┘                    └──────┘
pid                                  └──┘└┘                 └┘                    └────┘
st                             └────────────────────────────────────────────────────────────┘
259      let ⟨a, hat, has⟩ := this in ⟨a, has, insert_subset.mpr ⟨hat, h₁⟩⟩)
id       └─┘    └─┘  └─┘     └──┘             └───────────┘└──┘
src                                            └───────────┘└──┘
typ      └─┘    └─┘  └─┘     └──┘             └───────────┘└──┘
260    (assume ⟨a, hat, has⟩,
id                └─┘  └─┘
typ               └─┘  └─┘
261      let ⟨h₁, h₂⟩ := insert_subset.mp has in
id       └─┘  └┘  └┘     └───────────┘└─┘
src                      └───────────┘└─┘
typ      └─┘  └┘  └┘     └───────────┘└─┘
262      ⟨h₂, assume h, hat $ h h₁⟩)
id                           
typ                          
263  
264  lemma ssubset_insert {s : finset α} {a : α} (h : a ∉ s) : s ⊂ insert a s :=
id                             └────┘                       └────┘  
src                            └────┘                            └────┘
typ                            └────┘                       └────┘  
doc                            └────┘
265  ssubset_iff.mpr ⟨a, h, subset.refl _⟩
id   └─────────┘└──┘      └─────────┘
src  └─────────┘└──┘        └─────────┘
typ  └─────────┘└──┘      └─────────┘
266  
267  @[recursor 6] protected theorem induction {α : Type*} {p : finset α → Prop} [decidable_eq α]
id                                                              └────┘           └──────────┘ 
src                                                             └────┘            └──────────┘
typ                                                             └────┘           └──────────┘ 
doc    └──────┘                                                 └────┘
268    (h₁ : p ∅) (h₂ : ∀ ⦃a : α⦄ {s : finset α}, a ∉ s → p s → p (insert a s)) : ∀ s, p s
id                                  └────┘               └────┘            
src                                   └────┘                     └────┘
typ                                 └────┘               └────┘            
doc                                    └────┘
269  | ⟨s, nd⟩ := multiset.induction_on s (λ _, h₁) (λ a s IH nd, begin
id        └┘     └───────────────────┘        └┘       └┘ └┘
src               └───────────────────┘
typ       └┘     └───────────────────┘        └┘       └┘ └┘
st                                                                └─────
270      cases nodup_cons.1 nd with m nd',
id             └────────┘   └┘
src      └────┘└────────┘└─┘  └─────────┘
typ      └────┘└────────┘└─┘└┘└─────────┘
doc      └────┘          └─┘  └─────────┘
txt      └────┘          └─┘  └─────────┘
par      └────┘          └─┘  └─────────┘
pid                     └─┘  └─────────┘
st   ───────────────────────────────────┘└─
271      rw [← (eq_of_veq _ : insert a (finset.mk s _) = ⟨a::s, nd⟩)],
id              └───────┘     └────┘    └───────┘        └┘  └┘
src      └────┘ └───────┘└───┘└────┘  └───────┘ └──┘  └┘ └┘  └─┘
typ      └────┘ └───────┘└───┘└────┘  └───────┘ └──┘ └┘└┘└┘└─┘
doc      └────┘          └───┘                  └──┘   └┘ └┘  └─┘
txt      └────┘          └───┘                  └──┘      └┘  └─┘
par      └────┘          └───┘                  └──┘      └┘  └─┘
pid        └──┘          └───┘                  └──┘      └┘  └─┘
st   ──────────────────────────────────────────────────────────────┘└──
272      { exact h₂ (by exact m) (IH nd') },
id               └┘              └┘ └─┘
src        └────┘     └─────┘ └┘      └┘
typ        └────┘└┘   └─────┘└┘ └┘└─┘└┘
doc        └────┘     └─────┘ └┘      └┘
txt        └────┘     └─────┘ └┘      └┘
par        └────┘     └─────┘ └┘      └┘
pid                  └─────┘ └┘      
st   ─────┘└──────────┘└──────┘└─────────┘└┘
273      { rw [insert_val, ndinsert_of_not_mem m] }
id             └────────┘  └─────────────────┘ 
src        └──┘└────────┘└┘└─────────────────┘ └┘
typ        └──┘└────────┘└┘└─────────────────┘└┘
doc        └──┘          └┘                    └┘
txt        └──┘          └┘                    └┘
par        └──┘          └┘                    └┘
pid          └┘          └┘                    
st   ───────────────────┘└─────────────────────┘└─
274    end) nd
st   ────┘
275  
276  /--
277  To prove a proposition about an arbitrary `finset α`,
278  it suffices to prove it for the empty `finset`,
279  and to show that if it holds for some `finset α`,
280  then it holds for the `finset` obtained by inserting a new element.
281  -/
282  @[elab_as_eliminator] protected theorem induction_on {α : Type*} {p : finset α → Prop} [decidable_eq α]
id                                                                         └────┘           └──────────┘ 
src                                                                        └────┘            └──────────┘
typ                                                                        └────┘           └──────────┘ 
doc    └────────────────┘                                                  └────┘
283    (s : finset α) (h₁ : p ∅) (h₂ : ∀ ⦃a : α⦄ {s : finset α}, a ∉ s → p s → p (insert a s)) : p s :=
id          └────┘                                └────┘               └────┘        
src         └────┘                                   └────┘                     └────┘
typ         └────┘                                └────┘               └────┘        
doc         └────┘                                    └────┘
284  finset.induction h₁ h₂ s
id   └──────────────┘ └┘ └┘ 
src  └──────────────┘
typ  └──────────────┘ └┘ └┘ 
285  
286  @[simp] theorem singleton_eq_singleton (a : α) : _root_.singleton a = ι a := rfl
id                                                   └──────────────┘        └─┘
src                                                   └──────────────┘          └─┘
typ                                                  └──────────────┘        └─┘
doc    └──┘                                                                
287  
288  @[simp] theorem insert_empty_eq_singleton (a : α) : {a} = ι a := rfl
id                                                              └─┘
src                                                                └─┘
typ                                                             └─┘
doc    └──┘                                                    
289  
290  @[simp] theorem insert_singleton_self_eq (a : α) : ({a, a} : finset α) = ι a :=
id                                                           └────┘     
src                                                             └────┘     
typ                                                          └────┘     
doc    └──┘                                                       └────┘      
291  insert_eq_of_mem $ mem_singleton_self _
id   └──────────────┘   └────────────────┘
src  └──────────────┘   └────────────────┘
typ  └──────────────┘   └────────────────┘
292  
293  /-! ### union -/
294  
295  /-- `s ∪ t` is the set such that `a ∈ s ∪ t` iff `a ∈ s` or `a ∈ t`. -/
296  instance : has_union (finset α) := ⟨λ s₁ s₂, ⟨_, nodup_ndunion s₁.1 s₂.2⟩⟩
id              └───────┘  └────┘         └┘ └┘      └───────────┘ └┘  └┘
src             └───────┘  └────┘                     └───────────┘       
typ             └───────┘  └────┘         └┘ └┘      └───────────┘ └┘  └┘
doc                        └────┘
297  
298  theorem union_val_nd (s₁ s₂ : finset α) : (s₁ ∪ s₂).1 = ndunion s₁.1 s₂.1 := rfl
id                                 └────┘      └┘  └┘    └─────┘ └┘  └┘     └─┘
src                                └────┘                 └─────┘            └─┘
typ                                └────┘      └┘  └┘    └─────┘ └┘  └┘     └─┘
doc                                └────┘                    └─────┘
299  
300  @[simp] theorem union_val (s₁ s₂ : finset α) : (s₁ ∪ s₂).1 = s₁.1 ∪ s₂.1 :=
id                                      └────┘      └┘  └┘    └┘   └┘
src                                     └────┘                        
typ                                     └────┘      └┘  └┘    └┘   └┘
doc    └──┘                             └────┘
301  ndunion_eq_union s₁.2
id   └──────────────┘ └┘
src  └──────────────┘   
typ  └──────────────┘ └┘
302  
303  @[simp] theorem mem_union {a : α} {s₁ s₂ : finset α} : a ∈ s₁ ∪ s₂ ↔ a ∈ s₁ ∨ a ∈ s₂ := mem_ndunion
id                                             └────┘       └┘  └┘    └┘    └┘    └─────────┘
src                                             └────┘                                 └─────────┘
typ                                            └────┘       └┘  └┘    └┘    └┘    └─────────┘
doc    └──┘                                     └────┘
304  
305  theorem mem_union_left {a : α} {s₁ : finset α} (s₂ : finset α) (h : a ∈ s₁) : a ∈ s₁ ∪ s₂ := mem_union.2 $ or.inl h
id                                       └────┘         └────┘          └┘      └┘  └┘    └───────┘    └────┘ 
src                                       └────┘          └────┘                               └───────┘    └────┘
typ                                      └────┘         └────┘          └┘      └┘  └┘    └───────┘    └────┘ 
doc                                       └────┘          └────┘
306  
307  theorem mem_union_right {a : α} {s₂ : finset α} (s₁ : finset α) (h : a ∈ s₂) : a ∈ s₁ ∪ s₂ := mem_union.2 $ or.inr h
id                                        └────┘         └────┘          └┘      └┘  └┘    └───────┘    └────┘ 
src                                        └────┘          └────┘                               └───────┘    └────┘
typ                                       └────┘         └────┘          └┘      └┘  └┘    └───────┘    └────┘ 
doc                                        └────┘          └────┘
308  
309  theorem not_mem_union {a : α} {s₁ s₂ : finset α} : a ∉ s₁ ∪ s₂ ↔ a ∉ s₁ ∧ a ∉ s₂ :=
id                                         └────┘       └┘  └┘    └┘    └┘
src                                         └────┘                          
typ                                        └────┘       └┘  └┘    └┘    └┘
doc                                         └────┘
310  by rw [mem_union, not_or_distrib]
id          └───────┘  └────────────┘
src     └──┘└───────┘└┘└────────────┘└─
typ     └──┘└───────┘└┘└────────────┘└─
doc     └──┘         └┘              └─
txt     └──┘         └┘              └─
par     └──┘         └┘              └─
pid       └┘         └┘              
st     └────────────┘└──────────────┘
311  
src  
typ  
doc  
txt  
par  
pid  
st   
312  @[simp] lemma coe_union (s₁ s₂ : finset α) : ↑(s₁ ∪ s₂) = (↑s₁ ∪ ↑s₂ : set α) := set.ext $ λ x, mem_union
id                                    └────┘      └┘  └┘    └┘  └┘   └─┘      └─────┘       └───────┘
src                                   └────┘                          └─┘       └─────┘        └───────┘
typ                                   └────┘      └┘  └┘    └┘  └┘   └─┘      └─────┘       └───────┘
doc    └──┘                           └────┘
313  
314  theorem union_subset {s₁ s₂ s₃ : finset α} (h₁ : s₁ ⊆ s₃) (h₂ : s₂ ⊆ s₃) : s₁ ∪ s₂ ⊆ s₃ :=
id                                    └────┘         └┘  └┘        └┘  └┘    └┘  └┘  └┘
src                                   └────┘                                         
typ                                   └────┘         └┘  └┘        └┘  └┘    └┘  └┘  └┘
doc                                   └────┘
315  val_le_iff.1 (ndunion_le.2 ⟨h₁, val_le_iff.2 h₂⟩)
id   └────────┘   └────────┘   └┘  └────────┘  └┘
src  └────────┘   └────────┘       └────────┘
typ  └────────┘   └────────┘   └┘  └────────┘  └┘
316  
317  theorem subset_union_left (s₁ s₂ : finset α) : s₁ ⊆ s₁ ∪ s₂ := λ x, mem_union_left _
id                                      └────┘     └┘  └┘  └┘        └────────────┘
src                                     └────┘                         └────────────┘
typ                                     └────┘     └┘  └┘  └┘        └────────────┘
doc                                     └────┘
318  
319  theorem subset_union_right (s₁ s₂ : finset α) : s₂ ⊆ s₁ ∪ s₂ := λ x, mem_union_right _
id                                       └────┘     └┘  └┘  └┘        └─────────────┘
src                                      └────┘                         └─────────────┘
typ                                      └────┘     └┘  └┘  └┘        └─────────────┘
doc                                      └────┘
320  
321  @[simp] theorem union_comm (s₁ s₂ : finset α) : s₁ ∪ s₂ = s₂ ∪ s₁ :=
id                                       └────┘     └┘  └┘  └┘  └┘
src                                      └────┘                 
typ                                      └────┘     └┘  └┘  └┘  └┘
doc    └──┘                              └────┘
322  ext.2 $ λ x, by simp only [mem_union, or_comm]
id   └─┘                      └───────┘  └─────┘
src  └─┘            └─────────┘└───────┘└┘└─────┘└─
typ  └─┘           └─────────┘└───────┘└┘└─────┘└─
doc                  └─────────┘         └┘       └─
txt                  └─────────┘         └┘       └─
par                  └─────────┘         └┘       └─
pid                      └──┘└┘         └┘       
st                  └───────────────────────────────
323  
src  
typ  
doc  
txt  
par  
pid  
st   
324  instance : is_commutative (finset α) (∪) := ⟨union_comm⟩
id              └────────────┘  └────┘          └────────┘
src             └────────────┘  └────┘           └────────┘
typ             └────────────┘  └────┘          └────────┘
doc                             └────┘
325  
326  @[simp] theorem union_assoc (s₁ s₂ s₃ : finset α) : (s₁ ∪ s₂) ∪ s₃ = s₁ ∪ (s₂ ∪ s₃) :=
id                                           └────┘      └┘  └┘   └┘  └┘   └┘  └┘
src                                          └────┘                            
typ                                          └────┘      └┘  └┘   └┘  └┘   └┘  └┘
doc    └──┘                                  └────┘
327  ext.2 $ λ x, by simp only [mem_union, or_assoc]
id   └─┘                      └───────┘  └──────┘
src  └─┘            └─────────┘└───────┘└┘└──────┘└─
typ  └─┘           └─────────┘└───────┘└┘└──────┘└─
doc                  └─────────┘         └┘        └─
txt                  └─────────┘         └┘        └─
par                  └─────────┘         └┘        └─
pid                      └──┘└┘         └┘        
st                  └────────────────────────────────
328  
src  
typ  
doc  
txt  
par  
pid  
st   
329  instance : is_associative (finset α) (∪) := ⟨union_assoc⟩
id              └────────────┘  └────┘          └─────────┘
src             └────────────┘  └────┘           └─────────┘
typ             └────────────┘  └────┘          └─────────┘
doc                             └────┘
330  
331  @[simp] theorem union_idempotent (s : finset α) : s ∪ s = s :=
id                                         └────┘         
src                                        └────┘           
typ                                        └────┘         
doc    └──┘                                └────┘
332  ext.2 $ λ _, mem_union.trans $ or_self _
id   └─┘        └───────┘└────┘   └─────┘
src  └─┘         └───────┘└────┘   └─────┘
typ  └─┘        └───────┘└────┘   └─────┘
333  
334  instance : is_idempotent (finset α) (∪) := ⟨union_idempotent⟩
id              └───────────┘  └────┘          └──────────────┘
src             └───────────┘  └────┘           └──────────────┘
typ             └───────────┘  └────┘          └──────────────┘
doc                            └────┘
335  
336  theorem union_left_comm (s₁ s₂ s₃ : finset α) : s₁ ∪ (s₂ ∪ s₃) = s₂ ∪ (s₁ ∪ s₃) :=
id                                       └────┘     └┘   └┘  └┘   └┘   └┘  └┘
src                                      └────┘                            
typ                                      └────┘     └┘   └┘  └┘   └┘   └┘  └┘
doc                                      └────┘
337  ext.2 $ λ _, by simp only [mem_union, or.left_comm]
id   └─┘                      └───────┘  └──────────┘
src  └─┘            └─────────┘└───────┘└┘└──────────┘└─
typ  └─┘           └─────────┘└───────┘└┘└──────────┘└─
doc                  └─────────┘         └┘            └─
txt                  └─────────┘         └┘            └─
par                  └─────────┘         └┘            └─
pid                      └──┘└┘         └┘            
st                  └────────────────────────────────────
338  
src  
typ  
doc  
txt  
par  
pid  
st   
339  theorem union_right_comm (s₁ s₂ s₃ : finset α) : (s₁ ∪ s₂) ∪ s₃ = (s₁ ∪ s₃) ∪ s₂ :=
id                                        └────┘      └┘  └┘   └┘   └┘  └┘   └┘
src                                       └────┘                             
typ                                       └────┘      └┘  └┘   └┘   └┘  └┘   └┘
doc                                       └────┘
340  ext.2 $ λ x, by simp only [mem_union, or_assoc, or_comm (x ∈ s₂)]
id   └─┘                      └───────┘  └──────┘  └─────┘    └┘
src  └─┘            └─────────┘└───────┘└┘└──────┘└┘└─────┘    └──
typ  └─┘           └─────────┘└───────┘└┘└──────┘└┘└─────┘ └┘└──
doc                  └─────────┘         └┘        └┘            └──
txt                  └─────────┘         └┘        └┘            └──
par                  └─────────┘         └┘        └┘            └──
pid                      └──┘└┘         └┘        └┘            └┘
st                  └──────────────────────────────────────────────────
341  
src  
typ  
doc  
txt  
par  
pid  
st   
342  @[simp] theorem union_self (s : finset α) : s ∪ s = s := union_idempotent s
id                                   └────┘             └──────────────┘ 
src                                  └────┘                 └──────────────┘
typ                                  └────┘             └──────────────┘ 
doc    └──┘                          └────┘
343  
344  @[simp] theorem union_empty (s : finset α) : s ∪ ∅ = s :=
id                                    └────┘         
src                                   └────┘          
typ                                   └────┘         
doc    └──┘                           └────┘
345  ext.2 $ λ x, mem_union.trans $ or_false _
id   └─┘        └───────┘└────┘   └──────┘
src  └─┘         └───────┘└────┘   └──────┘
typ  └─┘        └───────┘└────┘   └──────┘
346  
347  @[simp] theorem empty_union (s : finset α) : ∅ ∪ s = s :=
id                                    └────┘         
src                                   └────┘          
typ                                   └────┘         
doc    └──┘                           └────┘
348  ext.2 $ λ x, mem_union.trans $ false_or _
id   └─┘        └───────┘└────┘   └──────┘
src  └─┘         └───────┘└────┘   └──────┘
typ  └─┘        └───────┘└────┘   └──────┘
349  
350  theorem insert_eq (a : α) (s : finset α) : insert a s = {a} ∪ s := rfl
id                                 └────┘     └────┘           └─┘
src                                 └────┘      └────┘               └─┘
typ                                └────┘     └────┘           └─┘
doc                                 └────┘
351  
352  @[simp] theorem insert_union (a : α) (s t : finset α) : insert a s ∪ t = insert a (s ∪ t) :=
id                                              └────┘     └────┘      └────┘     
src                                              └────┘      └────┘         └────┘      
typ                                             └────┘     └────┘      └────┘     
doc    └──┘                                      └────┘
353  by simp only [insert_eq, union_assoc]
id                 └───────┘  └─────────┘
src     └─────────┘└───────┘└┘└─────────┘└─
typ     └─────────┘└───────┘└┘└─────────┘└─
doc     └─────────┘         └┘           └─
txt     └─────────┘         └┘           └─
par     └─────────┘         └┘           └─
pid         └──┘└┘         └┘           
st     └───────────────────────────────────
354  
src  
typ  
doc  
txt  
par  
pid  
st   
355  @[simp] theorem union_insert (a : α) (s t : finset α) : s ∪ insert a t = insert a (s ∪ t) :=
id                                              └────┘       └────┘    └────┘     
src                                              └────┘         └────┘      └────┘      
typ                                             └────┘       └────┘    └────┘     
doc    └──┘                                      └────┘
356  by simp only [insert_eq, union_left_comm]
id                 └───────┘  └─────────────┘
src     └─────────┘└───────┘└┘└─────────────┘└─
typ     └─────────┘└───────┘└┘└─────────────┘└─
doc     └─────────┘         └┘               └─
txt     └─────────┘         └┘               └─
par     └─────────┘         └┘               └─
pid         └──┘└┘         └┘               
st     └───────────────────────────────────────
357  
src  
typ  
doc  
txt  
par  
pid  
st   
358  theorem insert_union_distrib (a : α) (s t : finset α) : insert a (s ∪ t) = insert a s ∪ insert a t :=
id                                              └────┘     └────┘        └────┘    └────┘  
src                                              └────┘      └────┘           └────┘      └────┘
typ                                             └────┘     └────┘        └────┘    └────┘  
doc                                              └────┘
359  by simp only [insert_union, union_insert, insert_idem]
id                 └──────────┘  └──────────┘  └─────────┘
src     └─────────┘└──────────┘└┘└──────────┘└┘└─────────┘└─
typ     └─────────┘└──────────┘└┘└──────────┘└┘└─────────┘└─
doc     └─────────┘            └┘            └┘           └─
txt     └─────────┘            └┘            └┘           └─
par     └─────────┘            └┘            └┘           └─
pid         └──┘└┘            └┘            └┘           
st     └────────────────────────────────────────────────────
360  
src  
typ  
doc  
txt  
par  
pid  
st   
361  
src  
typ  
doc  
txt  
par  
pid  
st   
362  /-! ### inter -/
363  
364  /-- `s ∩ t` is the set such that `a ∈ s ∩ t` iff `a ∈ s` and `a ∈ t`. -/
365  instance : has_inter (finset α) := ⟨λ s₁ s₂, ⟨_, nodup_ndinter s₂.1 s₁.2⟩⟩
id              └───────┘  └────┘         └┘ └┘      └───────────┘ └┘  └┘
src             └───────┘  └────┘                     └───────────┘       
typ             └───────┘  └────┘         └┘ └┘      └───────────┘ └┘  └┘
doc                        └────┘
366  
367  theorem inter_val_nd (s₁ s₂ : finset α) : (s₁ ∩ s₂).1 = ndinter s₁.1 s₂.1 := rfl
id                                 └────┘      └┘  └┘    └─────┘ └┘  └┘     └─┘
src                                └────┘                 └─────┘            └─┘
typ                                └────┘      └┘  └┘    └─────┘ └┘  └┘     └─┘
doc                                └────┘                    └─────┘
368  
369  @[simp] theorem inter_val (s₁ s₂ : finset α) : (s₁ ∩ s₂).1 = s₁.1 ∩ s₂.1 :=
id                                      └────┘      └┘  └┘    └┘   └┘
src                                     └────┘                        
typ                                     └────┘      └┘  └┘    └┘   └┘
doc    └──┘                             └────┘
370  ndinter_eq_inter s₁.2
id   └──────────────┘ └┘
src  └──────────────┘   
typ  └──────────────┘ └┘
371  
372  @[simp] theorem mem_inter {a : α} {s₁ s₂ : finset α} : a ∈ s₁ ∩ s₂ ↔ a ∈ s₁ ∧ a ∈ s₂ := mem_ndinter
id                                             └────┘       └┘  └┘    └┘    └┘    └─────────┘
src                                             └────┘                                 └─────────┘
typ                                            └────┘       └┘  └┘    └┘    └┘    └─────────┘
doc    └──┘                                     └────┘
373  
374  theorem mem_of_mem_inter_left {a : α} {s₁ s₂ : finset α} (h : a ∈ s₁ ∩ s₂) : a ∈ s₁ := (mem_inter.1 h).1
id                                                 └────┘          └┘  └┘      └┘     └───────┘   
src                                                 └────┘                                └───────┘    
typ                                                └────┘          └┘  └┘      └┘     └───────┘   
doc                                                 └────┘
375  
376  theorem mem_of_mem_inter_right {a : α} {s₁ s₂ : finset α} (h : a ∈ s₁ ∩ s₂) : a ∈ s₂ := (mem_inter.1 h).2
id                                                  └────┘          └┘  └┘      └┘     └───────┘   
src                                                  └────┘                                └───────┘    
typ                                                 └────┘          └┘  └┘      └┘     └───────┘   
doc                                                  └────┘
377  
378  theorem mem_inter_of_mem {a : α} {s₁ s₂ : finset α} : a ∈ s₁ → a ∈ s₂ → a ∈ s₁ ∩ s₂ :=
id                                            └────┘       └┘     └┘     └┘  └┘
src                                            └────┘                            
typ                                           └────┘       └┘     └┘     └┘  └┘
doc                                            └────┘
379  and_imp.1 mem_inter.2
id   └─────┘  └───────┘
src  └─────┘  └───────┘
typ  └─────┘  └───────┘
380  
381  theorem inter_subset_left (s₁ s₂ : finset α) : s₁ ∩ s₂ ⊆ s₁ := λ a, mem_of_mem_inter_left
id                                      └────┘     └┘  └┘  └┘        └───────────────────┘
src                                     └────┘                         └───────────────────┘
typ                                     └────┘     └┘  └┘  └┘        └───────────────────┘
doc                                     └────┘
382  
383  theorem inter_subset_right (s₁ s₂ : finset α) : s₁ ∩ s₂ ⊆ s₂ := λ a, mem_of_mem_inter_right
id                                       └────┘     └┘  └┘  └┘        └────────────────────┘
src                                      └────┘                         └────────────────────┘
typ                                      └────┘     └┘  └┘  └┘        └────────────────────┘
doc                                      └────┘
384  
385  theorem subset_inter {s₁ s₂ s₃ : finset α} : s₁ ⊆ s₂ → s₁ ⊆ s₃ → s₁ ⊆ s₂ ∩ s₃ :=
id                                    └────┘     └┘  └┘   └┘  └┘   └┘  └┘  └┘
src                                   └────┘                               
typ                                   └────┘     └┘  └┘   └┘  └┘   └┘  └┘  └┘
doc                                   └────┘
386  by simp only [subset_iff, mem_inter] {contextual:=tt}; intros; split; trivial
id                 └────────┘  └───────┘               └┘
src     └─────────┘└────────┘└┘└───────┘└┘ └──────────┘└┘  └────┘  └───┘  └───────
typ     └─────────┘└────────┘└┘└───────┘└┘ └──────────┘└┘  └────┘  └───┘  └───────
doc     └─────────┘          └┘         └┘ └──────────┘    └────┘  └───┘  └───────
txt     └─────────┘          └┘         └┘ └──────────┘    └────┘  └───┘  └───────
par     └─────────┘          └┘         └┘ └──────────┘    └────┘  └───┘  └───────
pid         └──┘└┘          └┘          └──────────┘                          
st     └───────────────────────────────────────────────────────────────────────────
387  
src  
typ  
doc  
txt  
par  
pid  
st   
388  @[simp] lemma coe_inter (s₁ s₂ : finset α) : ↑(s₁ ∩ s₂) = (↑s₁ ∩ ↑s₂ : set α) := set.ext $ λ _, mem_inter
id                                    └────┘      └┘  └┘    └┘  └┘   └─┘      └─────┘       └───────┘
src                                   └────┘                          └─┘       └─────┘        └───────┘
typ                                   └────┘      └┘  └┘    └┘  └┘   └─┘      └─────┘       └───────┘
doc    └──┘                           └────┘
389  
390  @[simp] theorem union_inter_cancel_left {s t : finset α} : (s ∪ t) ∩ s = s :=
id                                                  └────┘             
src                                                 └────┘                
typ                                                 └────┘             
doc    └──┘                                         └────┘
391  by rw [← coe_inj, coe_inter, coe_union, set.union_inter_cancel_left]
id            └─────┘  └───────┘  └───────┘  └─────────────────────────┘
src     └────┘└─────┘└┘└───────┘└┘└───────┘└┘└─────────────────────────┘└─
typ     └────┘└─────┘└┘└───────┘└┘└───────┘└┘└─────────────────────────┘└─
doc     └────┘       └┘         └┘         └┘                           └─
txt     └────┘       └┘         └┘         └┘                           └─
par     └────┘       └┘         └┘         └┘                           └─
pid       └──┘       └┘         └┘         └┘                           
st     └────────────┘└─────────┘└─────────┘└───────────────────────────┘
392  
src  
typ  
doc  
txt  
par  
pid  
st   
393  @[simp] theorem union_inter_cancel_right {s t : finset α} : (s ∪ t) ∩ t = t :=
id                                                   └────┘             
src                                                  └────┘                
typ                                                  └────┘             
doc    └──┘                                          └────┘
394  by rw [← coe_inj, coe_inter, coe_union, set.union_inter_cancel_right]
id            └─────┘  └───────┘  └───────┘  └──────────────────────────┘
src     └────┘└─────┘└┘└───────┘└┘└───────┘└┘└──────────────────────────┘└─
typ     └────┘└─────┘└┘└───────┘└┘└───────┘└┘└──────────────────────────┘└─
doc     └────┘       └┘         └┘         └┘                            └─
txt     └────┘       └┘         └┘         └┘                            └─
par     └────┘       └┘         └┘         └┘                            └─
pid       └──┘       └┘         └┘         └┘                            
st     └────────────┘└─────────┘└─────────┘└────────────────────────────┘
395  
src  
typ  
doc  
txt  
par  
pid  
st   
396  @[simp] theorem inter_comm (s₁ s₂ : finset α) : s₁ ∩ s₂ = s₂ ∩ s₁ :=
id                                       └────┘     └┘  └┘  └┘  └┘
src                                      └────┘                 
typ                                      └────┘     └┘  └┘  └┘  └┘
doc    └──┘                              └────┘
397  ext.2 $ λ _, by simp only [mem_inter, and_comm]
id   └─┘                      └───────┘  └──────┘
src  └─┘            └─────────┘└───────┘└┘└──────┘└─
typ  └─┘           └─────────┘└───────┘└┘└──────┘└─
doc                  └─────────┘         └┘        └─
txt                  └─────────┘         └┘        └─
par                  └─────────┘         └┘        └─
pid                      └──┘└┘         └┘        
st                  └────────────────────────────────
398  
src  
typ  
doc  
txt  
par  
pid  
st   
399  @[simp] theorem inter_assoc (s₁ s₂ s₃ : finset α) : (s₁ ∩ s₂) ∩ s₃ = s₁ ∩ (s₂ ∩ s₃) :=
id                                           └────┘      └┘  └┘   └┘  └┘   └┘  └┘
src                                          └────┘                            
typ                                          └────┘      └┘  └┘   └┘  └┘   └┘  └┘
doc    └──┘                                  └────┘
400  ext.2 $ λ _, by simp only [mem_inter, and_assoc]
id   └─┘                      └───────┘  └───────┘
src  └─┘            └─────────┘└───────┘└┘└───────┘└─
typ  └─┘           └─────────┘└───────┘└┘└───────┘└─
doc                  └─────────┘         └┘         └─
txt                  └─────────┘         └┘         └─
par                  └─────────┘         └┘         └─
pid                      └──┘└┘         └┘         
st                  └─────────────────────────────────
401  
src  
typ  
doc  
txt  
par  
pid  
st   
402  @[simp] theorem inter_left_comm (s₁ s₂ s₃ : finset α) : s₁ ∩ (s₂ ∩ s₃) = s₂ ∩ (s₁ ∩ s₃) :=
id                                               └────┘     └┘   └┘  └┘   └┘   └┘  └┘
src                                              └────┘                            
typ                                              └────┘     └┘   └┘  └┘   └┘   └┘  └┘
doc    └──┘                                      └────┘
403  ext.2 $ λ _, by simp only [mem_inter, and.left_comm]
id   └─┘                      └───────┘  └───────────┘
src  └─┘            └─────────┘└───────┘└┘└───────────┘└─
typ  └─┘           └─────────┘└───────┘└┘└───────────┘└─
doc                  └─────────┘         └┘             └─
txt                  └─────────┘         └┘             └─
par                  └─────────┘         └┘             └─
pid                      └──┘└┘         └┘             
st                  └─────────────────────────────────────
404  
src  
typ  
doc  
txt  
par  
pid  
st   
405  @[simp] theorem inter_right_comm (s₁ s₂ s₃ : finset α) : (s₁ ∩ s₂) ∩ s₃ = (s₁ ∩ s₃) ∩ s₂ :=
id                                                └────┘      └┘  └┘   └┘   └┘  └┘   └┘
src                                               └────┘                             
typ                                               └────┘      └┘  └┘   └┘   └┘  └┘   └┘
doc    └──┘                                       └────┘
406  ext.2 $ λ _, by simp only [mem_inter, and.right_comm]
id   └─┘                      └───────┘  └────────────┘
src  └─┘            └─────────┘└───────┘└┘└────────────┘└─
typ  └─┘           └─────────┘└───────┘└┘└────────────┘└─
doc                  └─────────┘         └┘              └─
txt                  └─────────┘         └┘              └─
par                  └─────────┘         └┘              └─
pid                      └──┘└┘         └┘              
st                  └──────────────────────────────────────
407  
src  
typ  
doc  
txt  
par  
pid  
st   
408  @[simp] theorem inter_self (s : finset α) : s ∩ s = s :=
id                                   └────┘         
src                                  └────┘           
typ                                  └────┘         
doc    └──┘                          └────┘
409  ext.2 $ λ _, mem_inter.trans $ and_self _
id   └─┘        └───────┘└────┘   └──────┘
src  └─┘         └───────┘└────┘   └──────┘
typ  └─┘        └───────┘└────┘   └──────┘
410  
411  @[simp] theorem inter_empty (s : finset α) : s ∩ ∅ = ∅ :=
id                                    └────┘         
src                                   └────┘           
typ                                   └────┘         
doc    └──┘                           └────┘
412  ext.2 $ λ _, mem_inter.trans $ and_false _
id   └─┘        └───────┘└────┘   └───────┘
src  └─┘         └───────┘└────┘   └───────┘
typ  └─┘        └───────┘└────┘   └───────┘
413  
414  @[simp] theorem empty_inter (s : finset α) : ∅ ∩ s = ∅ :=
id                                    └────┘         
src                                   └────┘           
typ                                   └────┘         
doc    └──┘                           └────┘
415  ext.2 $ λ _, mem_inter.trans $ false_and _
id   └─┘        └───────┘└────┘   └───────┘
src  └─┘         └───────┘└────┘   └───────┘
typ  └─┘        └───────┘└────┘   └───────┘
416  
417  @[simp] theorem insert_inter_of_mem {s₁ s₂ : finset α} {a : α} (h : a ∈ s₂) :
id                                                └────┘                 └┘
src                                               └────┘                   
typ                                               └────┘                 └┘
doc    └──┘                                       └────┘
418    insert a s₁ ∩ s₂ = insert a (s₁ ∩ s₂) :=
id     └────┘  └┘  └┘  └────┘   └┘  └┘
src    └────┘           └────┘       
typ    └────┘  └┘  └┘  └────┘   └┘  └┘
419  ext.2 $ λ x, have x = a ∨ x ∈ s₂ ↔ x ∈ s₂, from or_iff_right_of_imp $ by rintro rfl; exact h,
id   └─┘                   └┘    └┘       └─────────────────┘                        
src  └─┘                                       └─────────────────┘      └────────┘  └────┘
typ  └─┘                   └┘    └┘       └─────────────────┘      └────────┘  └────┘
doc                                                                           └────────┘  └────┘
txt                                                                           └────────┘  └────┘
par                                                                           └────────┘  └────┘
pid                                                                                 └──┘       
st                                                                           └──────────────────┘
420  by simp only [mem_inter, mem_insert, or_and_distrib_left, this]
id                 └───────┘  └────────┘  └─────────────────┘  └──┘
src     └─────────┘└───────┘└┘└────────┘└┘└─────────────────┘└┘    └─
typ     └─────────┘└───────┘└┘└────────┘└┘└─────────────────┘└┘└──┘└─
doc     └─────────┘         └┘          └┘                   └┘    └─
txt     └─────────┘         └┘          └┘                   └┘    └─
par     └─────────┘         └┘          └┘                   └┘    └─
pid         └──┘└┘         └┘          └┘                   └┘    
st     └─────────────────────────────────────────────────────────────
421  
src  
typ  
doc  
txt  
par  
pid  
st   
422  @[simp] theorem inter_insert_of_mem {s₁ s₂ : finset α} {a : α} (h : a ∈ s₁) :
id                                                └────┘                 └┘
src                                               └────┘                   
typ                                               └────┘                 └┘
doc    └──┘                                       └────┘
423    s₁ ∩ insert a s₂ = insert a (s₁ ∩ s₂) :=
id     └┘  └────┘  └┘  └────┘   └┘  └┘
src        └────┘       └────┘       
typ    └┘  └────┘  └┘  └────┘   └┘  └┘
424  by rw [inter_comm, insert_inter_of_mem h, inter_comm]
id          └────────┘  └─────────────────┘   └────────┘
src     └──┘└────────┘└┘└─────────────────┘ └┘└────────┘└─
typ     └──┘└────────┘└┘└─────────────────┘└┘└────────┘└─
doc     └──┘          └┘                    └┘          └─
txt     └──┘          └┘                    └┘          └─
par     └──┘          └┘                    └┘          └─
pid       └┘          └┘                    └┘          
st     └─────────────┘└─────────────────────┘└──────────┘
425  
src  
typ  
doc  
txt  
par  
pid  
st   
426  @[simp] theorem insert_inter_of_not_mem {s₁ s₂ : finset α} {a : α} (h : a ∉ s₂) :
id                                                    └────┘                 └┘
src                                                   └────┘                   
typ                                                   └────┘                 └┘
doc    └──┘                                           └────┘
427    insert a s₁ ∩ s₂ = s₁ ∩ s₂ :=
id     └────┘  └┘  └┘  └┘  └┘
src    └────┘              
typ    └────┘  └┘  └┘  └┘  └┘
428  ext.2 $ λ x, have ¬ (x = a ∧ x ∈ s₂), by rintro ⟨rfl, H⟩; exact h H,
id   └─┘                     └┘                              
src  └─┘                                 └─────────────┘  └────┘ 
typ  └─┘                     └┘      └─────────────┘  └────┘
doc                                           └─────────────┘  └────┘ 
txt                                           └─────────────┘  └────┘ 
par                                           └─────────────┘  └────┘ 
pid                                                 └───────┘        
st                                           └─────────────────────────┘
429  by simp only [mem_inter, mem_insert, or_and_distrib_right, this, false_or]
id                 └───────┘  └────────┘  └──────────────────┘  └──┘  └──────┘
src     └─────────┘└───────┘└┘└────────┘└┘└──────────────────┘└┘    └┘└──────┘└─
typ     └─────────┘└───────┘└┘└────────┘└┘└──────────────────┘└┘└──┘└┘└──────┘└─
doc     └─────────┘         └┘          └┘                    └┘    └┘        └─
txt     └─────────┘         └┘          └┘                    └┘    └┘        └─
par     └─────────┘         └┘          └┘                    └┘    └┘        └─
pid         └──┘└┘         └┘          └┘                    └┘    └┘        
st     └────────────────────────────────────────────────────────────────────────
430  
src  
typ  
doc  
txt  
par  
pid  
st   
431  @[simp] theorem inter_insert_of_not_mem {s₁ s₂ : finset α} {a : α} (h : a ∉ s₁) :
id                                                    └────┘                 └┘
src                                                   └────┘                   
typ                                                   └────┘                 └┘
doc    └──┘                                           └────┘
432    s₁ ∩ insert a s₂ = s₁ ∩ s₂ :=
id     └┘  └────┘  └┘  └┘  └┘
src        └────┘          
typ    └┘  └────┘  └┘  └┘  └┘
433  by rw [inter_comm, insert_inter_of_not_mem h, inter_comm]
id          └────────┘  └─────────────────────┘   └────────┘
src     └──┘└────────┘└┘└─────────────────────┘ └┘└────────┘└─
typ     └──┘└────────┘└┘└─────────────────────┘└┘└────────┘└─
doc     └──┘          └┘                        └┘          └─
txt     └──┘          └┘                        └┘          └─
par     └──┘          └┘                        └┘          └─
pid       └┘          └┘                        └┘          
st     └─────────────┘└─────────────────────────┘└──────────┘
434  
src  
typ  
doc  
txt  
par  
pid  
st   
435  @[simp] theorem singleton_inter_of_mem {a : α} {s : finset α} (H : a ∈ s) : ι a ∩ s = ι a :=
id                                                      └────┘                    
src                                                      └────┘                        
typ                                                     └────┘                    
doc    └──┘                                              └────┘                           
436  show insert a ∅ ∩ s = insert a ∅, by rw [insert_inter_of_mem H, empty_inter]
id        └────┘      └────┘           └─────────────────┘   └─────────┘
src       └────┘        └────┘        └──┘└─────────────────┘ └┘└─────────┘└─
typ       └────┘      └────┘       └──┘└─────────────────┘└┘└─────────┘└─
doc                                       └──┘                    └┘           └─
txt                                       └──┘                    └┘           └─
par                                       └──┘                    └┘           └─
pid                                         └┘                    └┘           
st                                       └────────────────────────┘└───────────┘
437  
src  
typ  
doc  
txt  
par  
pid  
st   
438  @[simp] theorem singleton_inter_of_not_mem {a : α} {s : finset α} (H : a ∉ s) : ι a ∩ s = ∅ :=
id                                                          └────┘                   
src                                                          └────┘                        
typ                                                         └────┘                   
doc    └──┘                                                  └────┘                  
439  eq_empty_of_forall_not_mem $ by simp only [mem_inter, mem_singleton]; rintro x ⟨rfl, h⟩; exact H h
id   └────────────────────────┘                 └───────┘  └───────────┘                             
src  └────────────────────────┘      └─────────┘└───────┘└┘└───────────┘  └───────────────┘  └────┘  
typ  └────────────────────────┘      └─────────┘└───────┘└┘└───────────┘  └───────────────┘  └────┘
doc                                  └─────────┘         └┘               └───────────────┘  └────┘  
txt                                  └─────────┘         └┘               └───────────────┘  └────┘  
par                                  └─────────┘         └┘               └───────────────┘  └────┘  
pid                                      └──┘└┘         └┘                     └─────────┘         
st                                  └───────────────────────────────────────────────────────────────────
440  
src  
typ  
doc  
txt  
par  
pid  
st   
441  @[simp] theorem inter_singleton_of_mem {a : α} {s : finset α} (h : a ∈ s) : s ∩ ι a = ι a :=
id                                                      └────┘                    
src                                                      └────┘                        
typ                                                     └────┘                    
doc    └──┘                                              └────┘                           
442  by rw [inter_comm, singleton_inter_of_mem h]
id          └────────┘  └────────────────────┘ 
src     └──┘└────────┘└┘└────────────────────┘ └─
typ     └──┘└────────┘└┘└────────────────────┘└─
doc     └──┘          └┘                       └─
txt     └──┘          └┘                       └─
par     └──┘          └┘                       └─
pid       └┘          └┘                       
st     └─────────────┘└────────────────────────┘
443  
src  
typ  
doc  
txt  
par  
pid  
st   
444  @[simp] theorem inter_singleton_of_not_mem {a : α} {s : finset α} (h : a ∉ s) : s ∩ ι a = ∅ :=
id                                                          └────┘                   
src                                                          └────┘                        
typ                                                         └────┘                   
doc    └──┘                                                  └────┘                      
445  by rw [inter_comm, singleton_inter_of_not_mem h]
id          └────────┘  └────────────────────────┘ 
src     └──┘└────────┘└┘└────────────────────────┘ └─
typ     └──┘└────────┘└┘└────────────────────────┘└─
doc     └──┘          └┘                           └─
txt     └──┘          └┘                           └─
par     └──┘          └┘                           └─
pid       └┘          └┘                           
st     └─────────────┘└────────────────────────────┘
446  
src  
typ  
doc  
txt  
par  
pid  
st   
447  lemma inter_subset_inter {x y s t : finset α} (h : x ⊆ y) (h' : s ⊆ t) : x ∩ s ⊆ y ∩ t :=
id                                       └────┘                              
src                                      └────┘                                     
typ                                      └────┘                              
doc                                      └────┘
448  begin
st   └─────
449    intros a a_in,
src    └───────────┘
typ    └───────────┘
doc    └───────────┘
txt    └───────────┘
par    └───────────┘
pid          └─────┘
st   ──────────────┘└─
450    rw finset.mem_inter at a_in ⊢,
id        └──────────────┘
src    └─┘└──────────────┘└────────┘
typ    └─┘└──────────────┘└────────┘
doc    └─┘                └────────┘
txt    └─┘                └────────┘
par    └─┘                └────────┘
pid                      └────────┘
st   ──────────────────────────────┘└─
451    exact ⟨h a_in.1, h' a_in.2⟩
id                     └┘ └──┘
src    └────┘      └──┘      └──┘
typ    └────┘     └──┘└┘└──┘└──┘
doc    └────┘      └──┘      └──┘
txt    └────┘      └──┘      └──┘
par    └────┘      └──┘      └──┘
pid               └──┘      └─┘
st   ─────────────────────────────┘
452  end
st   └─┘
453  
454  lemma inter_subset_inter_right {x y s : finset α} (h : x ⊆ y) : x ∩ s ⊆ y ∩ s :=
id                                           └────┘                    
src                                          └────┘                         
typ                                          └────┘                    
doc                                          └────┘
455  finset.inter_subset_inter h (finset.subset.refl _)
id   └───────────────────────┘   └────────────────┘
src  └───────────────────────┘    └────────────────┘
typ  └───────────────────────┘   └────────────────┘
456  
457  lemma inter_subset_inter_left {x y s : finset α} (h : x ⊆ y) : s ∩ x ⊆ s ∩ y :=
id                                          └────┘                    
src                                         └────┘                         
typ                                         └────┘                    
doc                                         └────┘
458  finset.inter_subset_inter (finset.subset.refl _) h
id   └───────────────────────┘  └────────────────┘    
src  └───────────────────────┘  └────────────────┘
typ  └───────────────────────┘  └────────────────┘    
459  
460  /-! ### lattice laws -/
461  
462  instance : lattice (finset α) :=
id              └─────┘  └────┘ 
src             └─────┘  └────┘
typ             └─────┘  └────┘ 
doc             └─────┘  └────┘
463  { sup          := (∪),
id                     
src                    
typ                    
464    sup_le       := assume a b c, union_subset,
id                                └──────────┘
src                                  └──────────┘
typ                               └──────────┘
465    le_sup_left  := subset_union_left,
id                     └───────────────┘
src                    └───────────────┘
typ                    └───────────────┘
466    le_sup_right := subset_union_right,
id                     └────────────────┘
src                    └────────────────┘
typ                    └────────────────┘
467    inf          := (∩),
id                     
src                    
typ                    
468    le_inf       := assume a b c, subset_inter,
id                                └──────────┘
src                                  └──────────┘
typ                               └──────────┘
469    inf_le_left  := inter_subset_left,
id                     └───────────────┘
src                    └───────────────┘
typ                    └───────────────┘
470    inf_le_right := inter_subset_right,
id                     └────────────────┘
src                    └────────────────┘
typ                    └────────────────┘
471    ..finset.partial_order }
id       └──────────────────┘
src      └──────────────────┘
typ      └──────────────────┘
472  
473  @[simp] theorem sup_eq_union (s t : finset α) : s ⊔ t = s ∪ t := rfl
id                                       └────┘               └─┘
src                                      └────┘                    └─┘
typ                                      └────┘               └─┘
doc    └──┘                              └────┘
474  @[simp] theorem inf_eq_inter (s t : finset α) : s ⊓ t = s ∩ t := rfl
id                                       └────┘               └─┘
src                                      └────┘                    └─┘
typ                                      └────┘               └─┘
doc    └──┘                              └────┘
475  
476  instance : semilattice_inf_bot (finset α) :=
id              └─────────────────┘  └────┘ 
src             └─────────────────┘  └────┘
typ             └─────────────────┘  └────┘ 
doc             └─────────────────┘  └────┘
477  { bot := ∅, bot_le := empty_subset, ..finset.lattice.lattice }
id                        └──────────┘    └────────────────────┘
src                       └──────────┘    └────────────────────┘
typ                       └──────────┘    └────────────────────┘
478  
479  instance {α : Type*} [decidable_eq α] : semilattice_sup_bot (finset α) :=
id                         └──────────┘     └─────────────────┘  └────┘ 
src                        └──────────┘      └─────────────────┘  └────┘
typ                        └──────────┘     └─────────────────┘  └────┘ 
doc                                          └─────────────────┘  └────┘
480  { ..finset.lattice.semilattice_inf_bot, ..finset.lattice.lattice }
id       └────────────────────────────────┘    └────────────────────┘
src      └────────────────────────────────┘    └────────────────────┘
typ      └────────────────────────────────┘    └────────────────────┘
481  
482  instance : distrib_lattice (finset α) :=
id              └─────────────┘  └────┘ 
src             └─────────────┘  └────┘
typ             └─────────────┘  └────┘ 
doc             └─────────────┘  └────┘
483  { le_sup_inf := assume a b c, show (a ∪ b) ∩ (a ∪ c) ⊆ a ∪ b ∩ c,
id                                                   
src                                                          
typ                                                  
484      by simp only [subset_iff, mem_inter, mem_union, and_imp, or_imp_distrib] {contextual:=tt};
id                     └────────┘  └───────┘  └───────┘  └─────┘  └────────────┘               └┘
src         └─────────┘└────────┘└┘└───────┘└┘└───────┘└┘└─────┘└┘└────────────┘└┘ └──────────┘└┘
typ         └─────────┘└────────┘└┘└───────┘└┘└───────┘└┘└─────┘└┘└────────────┘└┘ └──────────┘└┘
doc         └─────────┘          └┘         └┘         └┘       └┘              └┘ └──────────┘  
txt         └─────────┘          └┘         └┘         └┘       └┘              └┘ └──────────┘  
par         └─────────┘          └┘         └┘         └┘       └┘              └┘ └──────────┘  
pid             └──┘└┘          └┘         └┘         └┘       └┘               └──────────┘  
st         └────────────────────────────────────────────────────────────────────────────────────────
485      simp only [true_or, imp_true_iff, true_and, or_true],
id                  └─────┘  └──────────┘  └──────┘  └─────┘
src      └─────────┘└─────┘└┘└──────────┘└┘└──────┘└┘└─────┘
typ      └─────────┘└─────┘└┘└──────────┘└┘└──────┘└┘└─────┘
doc      └─────────┘       └┘            └┘        └┘       
txt      └─────────┘       └┘            └┘        └┘       
par      └─────────┘       └┘            └┘        └┘       
pid          └──┘└┘       └┘            └┘        └┘       
st   ───────────────────────────────────────────────────────┘
486    ..finset.lattice.lattice }
id       └────────────────────┘
src      └────────────────────┘
typ      └────────────────────┘
487  
488  theorem inter_distrib_left (s t u : finset α) : s ∩ (t ∪ u) = (s ∩ t) ∪ (s ∩ u) := inf_sup_left
id                                       └────┘                           └──────────┘
src                                      └────┘                                   └──────────┘
typ                                      └────┘                           └──────────┘
doc                                      └────┘
489  
490  theorem inter_distrib_right (s t u : finset α) : (s ∪ t) ∩ u = (s ∩ u) ∪ (t ∩ u) := inf_sup_right
id                                        └────┘                           └───────────┘
src                                       └────┘                                   └───────────┘
typ                                       └────┘                           └───────────┘
doc                                       └────┘
491  
492  theorem union_distrib_left (s t u : finset α) : s ∪ (t ∩ u) = (s ∪ t) ∩ (s ∪ u) := sup_inf_left
id                                       └────┘                           └──────────┘
src                                      └────┘                                   └──────────┘
typ                                      └────┘                           └──────────┘
doc                                      └────┘
493  
494  theorem union_distrib_right (s t u : finset α) : (s ∩ t) ∪ u = (s ∪ u) ∩ (t ∪ u) := sup_inf_right
id                                        └────┘                           └───────────┘
src                                       └────┘                                   └───────────┘
typ                                       └────┘                           └───────────┘
doc                                       └────┘
495  
496  /-! ### erase -/
497  
498  /-- `erase s a` is the set `s - {a}`, that is, the elements of `s` which are
499    not equal to `a`. -/
500  def erase (s : finset α) (a : α) : finset α := ⟨_, nodup_erase_of_nodup a s.2⟩
id                  └────┘            └────┘         └──────────────────┘  
src                 └────┘              └────┘          └──────────────────┘    
typ                 └────┘            └────┘         └──────────────────┘  
doc                 └────┘              └────┘
501  
502  @[simp] theorem erase_val (s : finset α) (a : α) : (erase s a).1 = s.1.erase a := rfl
id                                  └────┘             └───┘       └───┘      └─┘
src                                 └────┘               └───┘          └───┘       └─┘
typ                                 └────┘             └───┘       └───┘      └─┘
doc    └──┘                         └────┘               └───┘             └───┘
503  
504  @[simp] theorem mem_erase {a b : α} {s : finset α} : a ∈ erase s b ↔ a ≠ b ∧ a ∈ s :=
id                                           └────┘       └───┘          
src                                           └────┘         └───┘              
typ                                          └────┘       └───┘          
doc    └──┘                                   └────┘          └───┘
505  mem_erase_iff_of_nodup s.2
id   └────────────────────┘ 
src  └────────────────────┘  
typ  └────────────────────┘ 
506  
507  theorem not_mem_erase (a : α) (s : finset α) : a ∉ erase s a := mem_erase_of_nodup s.2
id                                     └────┘       └───┘      └────────────────┘ 
src                                     └────┘         └───┘        └────────────────┘  
typ                                    └────┘       └───┘      └────────────────┘ 
doc                                     └────┘          └───┘
508  
509  @[simp] theorem erase_empty (a : α) : erase ∅ a = ∅ := rfl
id                                        └───┘        └─┘
src                                        └───┘         └─┘
typ                                       └───┘        └─┘
doc    └──┘                                └───┘
510  
511  theorem ne_of_mem_erase {a b : α} {s : finset α} : b ∈ erase s a → b ≠ a :=
id                                         └────┘       └───┘       
src                                         └────┘         └───┘         
typ                                        └────┘       └───┘       
doc                                         └────┘          └───┘
512  by simp only [mem_erase]; exact and.left
id                 └───────┘         └──────┘
src     └─────────┘└───────┘  └────┘└──────┘
typ     └─────────┘└───────┘  └────┘└──────┘
doc     └─────────┘           └────┘        
txt     └─────────┘           └────┘        
par     └─────────┘           └────┘        
pid         └──┘└┘                        
st     └──────────────────────────────────────
513  
src  
typ  
doc  
txt  
par  
pid  
st   
514  theorem mem_of_mem_erase {a b : α} {s : finset α} : b ∈ erase s a → b ∈ s := mem_of_mem_erase
id                                          └────┘       └───┘           └──────────────┘
src                                          └────┘         └───┘               └──────────────┘
typ                                         └────┘       └───┘           └──────────────┘
doc                                          └────┘          └───┘
515  
516  theorem mem_erase_of_ne_of_mem {a b : α} {s : finset α} : a ≠ b → a ∈ s → a ∈ erase s b :=
id                                                └────┘                 └───┘  
src                                                └────┘                       └───┘
typ                                               └────┘                 └───┘  
doc                                                └────┘                          └───┘
517  by simp only [mem_erase]; exact and.intro
id                 └───────┘         └───────┘
src     └─────────┘└───────┘  └────┘└───────┘
typ     └─────────┘└───────┘  └────┘└───────┘
doc     └─────────┘           └────┘         
txt     └─────────┘           └────┘         
par     └─────────┘           └────┘         
pid         └──┘└┘                         
st     └───────────────────────────────────────
518  
src  
typ  
doc  
txt  
par  
pid  
st   
519  theorem erase_insert {a : α} {s : finset α} (h : a ∉ s) : erase (insert a s) a = s :=
id                                    └────┘              └───┘  └────┘      
src                                    └────┘                 └───┘  └────┘        
typ                                   └────┘              └───┘  └────┘      
doc                                    └────┘                  └───┘
520  ext.2 $ assume x, by simp only [mem_erase, mem_insert, and_or_distrib_left, not_and_self, false_or];
id   └─┘                           └───────┘  └────────┘  └─────────────────┘  └──────────┘  └──────┘
src  └─┘                 └─────────┘└───────┘└┘└────────┘└┘└─────────────────┘└┘└──────────┘└┘└──────┘
typ  └─┘                └─────────┘└───────┘└┘└────────┘└┘└─────────────────┘└┘└──────────┘└┘└──────┘
doc                       └─────────┘         └┘          └┘                   └┘            └┘        
txt                       └─────────┘         └┘          └┘                   └┘            └┘        
par                       └─────────┘         └┘          └┘                   └┘            └┘        
pid                           └──┘└┘         └┘          └┘                   └┘            └┘        
st                       └────────────────────────────────────────────────────────────────────────────────
521  apply and_iff_right_of_imp; rintro H rfl; exact h H
id         └──────────────────┘                       
src  └────┘└──────────────────┘  └──────────┘  └────┘  
typ  └────┘└──────────────────┘  └──────────┘  └────┘
doc  └────┘                      └──────────┘  └────┘  
txt  └────┘                      └──────────┘  └────┘  
par  └────┘                      └──────────┘  └────┘  
pid                                   └────┘         
st   ────────────────────────────────────────────────────
522  
src  
typ  
doc  
txt  
par  
pid  
st   
523  theorem insert_erase {a : α} {s : finset α} (h : a ∈ s) : insert a (erase s a) = s :=
id                                    └────┘              └────┘   └───┘     
src                                    └────┘                 └────┘    └───┘      
typ                                   └────┘              └────┘   └───┘     
doc                                    └────┘                            └───┘
524  ext.2 $ assume x, by simp only [mem_insert, mem_erase, or_and_distrib_left, dec_em, true_and];
id   └─┘                           └────────┘  └───────┘  └─────────────────┘  └────┘  └──────┘
src  └─┘                 └─────────┘└────────┘└┘└───────┘└┘└─────────────────┘└┘└────┘└┘└──────┘
typ  └─┘                └─────────┘└────────┘└┘└───────┘└┘└─────────────────┘└┘└────┘└┘└──────┘
doc                       └─────────┘          └┘         └┘                   └┘      └┘        
txt                       └─────────┘          └┘         └┘                   └┘      └┘        
par                       └─────────┘          └┘         └┘                   └┘      └┘        
pid                           └──┘└┘          └┘         └┘                   └┘      └┘        
st                       └──────────────────────────────────────────────────────────────────────────
525  apply or_iff_right_of_imp; rintro rfl; exact h
id         └─────────────────┘                    
src  └────┘└─────────────────┘  └────────┘  └────┘ 
typ  └────┘└─────────────────┘  └────────┘  └────┘
doc  └────┘                     └────────┘  └────┘ 
txt  └────┘                     └────────┘  └────┘ 
par  └────┘                     └────────┘  └────┘ 
pid                                  └──┘        
st   ───────────────────────────────────────────────
526  
src  
typ  
doc  
txt  
par  
pid  
st   
527  theorem erase_subset_erase (a : α) {s t : finset α} (h : s ⊆ t) : erase s a ⊆ erase t a :=
id                                            └────┘              └───┘    └───┘  
src                                            └────┘                 └───┘      └───┘
typ                                           └────┘              └───┘    └───┘  
doc                                            └────┘                  └───┘       └───┘
528  val_le_iff.1 $ erase_le_erase _ $ val_le_iff.2 h
id   └────────┘    └────────────┘     └────────┘  
src  └────────┘    └────────────┘     └────────┘
typ  └────────┘    └────────────┘     └────────┘  
529  
530  theorem erase_subset (a : α) (s : finset α) : erase s a ⊆ s := erase_subset _ _
id                                    └────┘     └───┘        └──────────┘
src                                    └────┘      └───┘           └──────────┘
typ                                   └────┘     └───┘        └──────────┘
doc                                    └────┘      └───┘
531  
532  @[simp] lemma coe_erase (a : α) (s : finset α) : ↑(erase s a) = (↑s \ {a} : set α) :=
id                                       └────┘      └───┘            └─┘ 
src                                       └────┘       └───┘                └─┘
typ                                      └────┘      └───┘            └─┘ 
doc    └──┘                               └────┘        └───┘
533  set.ext $ λ _, mem_erase.trans $ by rw [and_comm, set.mem_diff, set.mem_singleton_iff]; refl
id   └─────┘       └───────┘└────┘          └──────┘  └──────────┘  └───────────────────┘
src  └─────┘        └───────┘└────┘      └──┘└──────┘└┘└──────────┘└┘└───────────────────┘  └────
typ  └─────┘       └───────┘└────┘      └──┘└──────┘└┘└──────────┘└┘└───────────────────┘  └────
doc                                      └──┘        └┘            └┘                       └────
txt                                      └──┘        └┘            └┘                       └────
par                                      └──┘        └┘            └┘                       └────
pid                                        └┘        └┘            └┘                           
st                                      └───────────┘└────────────┘└─────────────────────┘└──────
534  
src  
typ  
doc  
txt  
par  
pid  
st   
535  lemma erase_ssubset {a : α} {s : finset α} (h : a ∈ s) : s.erase a ⊂ s :=
id                                   └────┘              └────┘   
src                                   └────┘                  └────┘   
typ                                  └────┘              └────┘   
doc                                   └────┘                   └────┘
536  calc s.erase a ⊂ insert a (s.erase a) : ssubset_insert $ not_mem_erase _ _
id        └────┘    └────┘   └────┘     └────────────┘   └───────────┘
src        └────┘     └────┘     └────┘      └────────────┘   └───────────┘
typ       └────┘    └────┘   └────┘     └────────────┘   └───────────┘
doc        └────┘                └────┘
537    ... = _ : insert_erase h
id               └──────────┘ 
src              └──────────┘
typ              └──────────┘ 
538  
539  theorem erase_eq_of_not_mem {a : α} {s : finset α} (h : a ∉ s) : erase s a = s :=
id                                           └────┘              └───┘    
src                                           └────┘                 └───┘     
typ                                          └────┘              └───┘    
doc                                           └────┘                  └───┘
540  eq_of_veq $ erase_of_not_mem h
id   └───────┘   └──────────────┘ 
src  └───────┘   └──────────────┘
typ  └───────┘   └──────────────┘ 
541  
542  theorem subset_insert_iff {a : α} {s t : finset α} : s ⊆ insert a t ↔ erase s a ⊆ t :=
id                                           └────┘       └────┘    └───┘    
src                                           └────┘         └────┘      └───┘     
typ                                          └────┘       └────┘    └───┘    
doc                                           └────┘                       └───┘
543  by simp only [subset_iff, or_iff_not_imp_left, mem_erase, mem_insert, and_imp];
id                 └────────┘  └─────────────────┘  └───────┘  └────────┘  └─────┘
src     └─────────┘└────────┘└┘└─────────────────┘└┘└───────┘└┘└────────┘└┘└─────┘
typ     └─────────┘└────────┘└┘└─────────────────┘└┘└───────┘└┘└────────┘└┘└─────┘
doc     └─────────┘          └┘                   └┘         └┘          └┘       
txt     └─────────┘          └┘                   └┘         └┘          └┘       
par     └─────────┘          └┘                   └┘         └┘          └┘       
pid         └──┘└┘          └┘                   └┘         └┘          └┘       
st     └─────────────────────────────────────────────────────────────────────────────
544  exact forall_congr (λ x, forall_swap)
id         └──────────┘       └─────────┘
src  └────┘└──────────┘  └──┘└─────────┘└─
typ  └────┘└──────────┘  └──┘└─────────┘└─
doc  └────┘              └──┘           └─
txt  └────┘              └──┘           └─
par  └────┘              └──┘           └─
pid                     └──┘           
st   ──────────────────────────────────────
545  
src  
typ  
doc  
txt  
par  
pid  
st   
546  theorem erase_insert_subset (a : α) (s : finset α) : erase (insert a s) a ⊆ s :=
id                                           └────┘     └───┘  └────┘      
src                                           └────┘      └───┘  └────┘        
typ                                          └────┘     └───┘  └────┘      
doc                                           └────┘      └───┘
547  subset_insert_iff.1 $ subset.refl _
id   └───────────────┘    └─────────┘
src  └───────────────┘    └─────────┘
typ  └───────────────┘    └─────────┘
548  
549  theorem insert_erase_subset (a : α) (s : finset α) : s ⊆ insert a (erase s a) :=
id                                           └────┘       └────┘   └───┘  
src                                           └────┘         └────┘    └───┘
typ                                          └────┘       └────┘   └───┘  
doc                                           └────┘                    └───┘
550  subset_insert_iff.2 $ subset.refl _
id   └───────────────┘    └─────────┘
src  └───────────────┘    └─────────┘
typ  └───────────────┘    └─────────┘
551  
552  /-! ### sdiff -/
553  
554  /-- `s \ t` is the set consisting of the elements of `s` that are not in `t`. -/
555  instance : has_sdiff (finset α) := ⟨λs₁ s₂, ⟨s₁.1 - s₂.1, nodup_of_le (sub_le_self _ _) s₁.2⟩⟩
id              └───────┘  └────┘        └┘ └┘   └┘   └┘   └─────────┘  └─────────┘      └┘
src             └───────┘  └────┘                           └─────────┘  └─────────┘        
typ             └───────┘  └────┘        └┘ └┘   └┘   └┘   └─────────┘  └─────────┘      └┘
doc                        └────┘
556  
557  @[simp] theorem mem_sdiff {a : α} {s₁ s₂ : finset α} :
id                                             └────┘ 
src                                             └────┘
typ                                            └────┘ 
doc    └──┘                                     └────┘
558    a ∈ s₁ \ s₂ ↔ a ∈ s₁ ∧ a ∉ s₂ := mem_sub_of_nodup s₁.2
id       └┘  └┘    └┘    └┘    └──────────────┘ └┘
src                               └──────────────┘   
typ      └┘  └┘    └┘    └┘    └──────────────┘ └┘
559  
560  @[simp] theorem sdiff_union_of_subset {s₁ s₂ : finset α} (h : s₁ ⊆ s₂) : (s₂ \ s₁) ∪ s₁ = s₂ :=
id                                                  └────┘        └┘  └┘     └┘  └┘   └┘  └┘
src                                                 └────┘                                
typ                                                 └────┘        └┘  └┘     └┘  └┘   └┘  └┘
doc    └──┘                                         └────┘
561  ext.2 $ λ a, by simpa only [mem_sdiff, mem_union, or_comm,
id   └─┘                       └───────┘  └───────┘  └─────┘
src  └─┘            └──────────┘└───────┘└┘└───────┘└┘└─────┘└─
typ  └─┘           └──────────┘└───────┘└┘└───────┘└┘└─────┘└─
doc                  └──────────┘         └┘         └┘       └─
txt                  └──────────┘         └┘         └┘       └─
par                  └──────────┘         └┘         └┘       └─
pid                       └──┘└┘         └┘         └┘       └─
st                  └───────────────────────────────────────────
562    or_and_distrib_left, dec_em, and_true] using or_iff_right_of_imp (@h a)
id     └─────────────────┘  └────┘  └──────┘        └─────────────────┘    
src  ─┘└─────────────────┘└┘└────┘└┘└──────┘└──────┘└─────────────────┘    └─
typ  ─┘└─────────────────┘└┘└────┘└┘└──────┘└──────┘└─────────────────┘  └─
doc  ─┘                   └┘      └┘        └──────┘                       └─
txt  ─┘                   └┘      └┘        └──────┘                       └─
par  ─┘                   └┘      └┘        └──────┘                       └─
pid  ─┘                   └┘      └┘        └────┘                       
st   ──────────────────────────────────────────────────────────────────────────
563  
src  
typ  
doc  
txt  
par  
pid  
st   
564  @[simp] theorem union_sdiff_of_subset {s₁ s₂ : finset α} (h : s₁ ⊆ s₂) : s₁ ∪ (s₂ \ s₁) = s₂ :=
id                                                  └────┘        └┘  └┘    └┘   └┘  └┘   └┘
src                                                 └────┘                                
typ                                                 └────┘        └┘  └┘    └┘   └┘  └┘   └┘
doc    └──┘                                         └────┘
565  (union_comm _ _).trans (sdiff_union_of_subset h)
id    └────────┘     └───┘   └───────────────────┘ 
src   └────────┘     └───┘   └───────────────────┘
typ   └────────┘     └───┘   └───────────────────┘ 
566  
567  theorem inter_sdiff (s t u : finset α) : s ∩ (t \ u) = s ∩ t \ u :=
id                                └────┘                 
src                               └────┘                      
typ                               └────┘                 
doc                               └────┘
568  by { ext x, simp [and_assoc] }
id                     └───────┘
src       └───┘  └────┘└───────┘└┘
typ       └───┘  └────┘└───────┘└┘
doc       └───┘  └────┘         └┘
txt       └───┘  └────┘         └┘
par       └───┘  └────┘         └┘
pid          └┘               
st     └──────┘└─────────────────┘└┘
569  
570  @[simp] theorem inter_sdiff_self (s₁ s₂ : finset α) : s₁ ∩ (s₂ \ s₁) = ∅ :=
id                                             └────┘     └┘   └┘  └┘   
src                                            └────┘                    
typ                                            └────┘     └┘   └┘  └┘   
doc    └──┘                                    └────┘
571  eq_empty_of_forall_not_mem $
id   └────────────────────────┘
src  └────────────────────────┘
typ  └────────────────────────┘
572  by simp only [mem_inter, mem_sdiff]; rintro x ⟨h, _, hn⟩; exact hn h
id                 └───────┘  └───────┘                              └┘ 
src     └─────────┘└───────┘└┘└───────┘  └─────────────────┘  └────┘   
typ     └─────────┘└───────┘└┘└───────┘  └─────────────────┘  └────┘└┘
doc     └─────────┘         └┘           └─────────────────┘  └────┘   
txt     └─────────┘         └┘           └─────────────────┘  └────┘   
par     └─────────┘         └┘           └─────────────────┘  └────┘   
pid         └──┘└┘         └┘                 └───────────┘          
st     └──────────────────────────────────────────────────────────────────
573  
src  
typ  
doc  
txt  
par  
pid  
st   
574  @[simp] theorem sdiff_inter_self (s₁ s₂ : finset α) : (s₂ \ s₁) ∩ s₁ = ∅ :=
id                                             └────┘      └┘  └┘   └┘  
src                                            └────┘                    
typ                                            └────┘      └┘  └┘   └┘  
doc    └──┘                                    └────┘
575  (inter_comm _ _).trans (inter_sdiff_self _ _)
id    └────────┘     └───┘   └──────────────┘
src   └────────┘     └───┘   └──────────────┘
typ   └────────┘     └───┘   └──────────────┘
576  
577  theorem sdiff_subset_sdiff {s₁ s₂ t₁ t₂ : finset α} (h₁ : t₁ ⊆ t₂) (h₂ : s₂ ⊆ s₁) : t₁ \ s₁ ⊆ t₂ \ s₂ :=
id                                             └────┘         └┘  └┘        └┘  └┘    └┘  └┘  └┘  └┘
src                                            └────┘                                             
typ                                            └────┘         └┘  └┘        └┘  └┘    └┘  └┘  └┘  └┘
doc                                            └────┘
578  by simpa only [subset_iff, mem_sdiff, and_imp] using λ a m₁ m₂, and.intro (h₁ m₁) (mt (@h₂ _) m₂)
id                  └────────┘  └───────┘  └─────┘                   └───────┘  └┘      └┘   └┘
src     └──────────┘└────────┘└┘└───────┘└┘└─────┘└──────┘ └────────┘└───────┘     └┘ └┘    └──┘  └─
typ     └──────────┘└────────┘└┘└───────┘└┘└─────┘└──────┘ └────────┘└───────┘ └┘  └┘ └┘  └┘└──┘  └─
doc     └──────────┘          └┘         └┘       └──────┘ └────────┘              └┘       └──┘  └─
txt     └──────────┘          └┘         └┘       └──────┘ └────────┘              └┘       └──┘  └─
par     └──────────┘          └┘         └┘       └──────┘ └────────┘              └┘       └──┘  └─
pid          └──┘└┘          └┘         └┘       └────┘ └────────┘              └┘       └──┘  
st     └───────────────────────────────────────────────────────────────────────────────────────────────
579  
src  
typ  
doc  
txt  
par  
pid  
st   
580  @[simp] lemma coe_sdiff (s₁ s₂ : finset α) : ↑(s₁ \ s₂) = (↑s₁ \ ↑s₂ : set α) :=
id                                    └────┘      └┘  └┘    └┘  └┘   └─┘ 
src                                   └────┘                          └─┘
typ                                   └────┘      └┘  └┘    └┘  └┘   └─┘ 
doc    └──┘                           └────┘
581  set.ext $ λ _, mem_sdiff
id   └─────┘       └───────┘
src  └─────┘        └───────┘
typ  └─────┘       └───────┘
582  
583  @[simp] lemma to_set_sdiff (s t : finset α) : (s \ t).to_set = s.to_set \ t.to_set :=
id                                     └────┘         └────┘   └─────┘  └─────┘
src                                    └────┘            └────┘    └─────┘   └─────┘
typ                                    └────┘         └────┘   └─────┘  └─────┘
doc    └──┘                            └────┘             └────┘     └─────┘    └─────┘
584  by apply finset.coe_sdiff
id            └──────────────┘
src     └────┘└──────────────┘
typ     └────┘└──────────────┘
doc     └────┘                
txt     └────┘                
par     └────┘                
pid                          
st     └───────────────────────
585  
src  
typ  
doc  
txt  
par  
pid  
st   
586  @[simp] theorem union_sdiff_self_eq_union {s t : finset α} : s ∪ (t \ s) = s ∪ t :=
id                                                    └────┘               
src                                                   └────┘                   
typ                                                   └────┘               
doc    └──┘                                           └────┘
587  ext.2 $ λ a, by simp only [mem_union, mem_sdiff, or_iff_not_imp_left,
id   └─┘                      └───────┘  └───────┘  └─────────────────┘
src  └─┘            └─────────┘└───────┘└┘└───────┘└┘└─────────────────┘└─
typ  └─┘           └─────────┘└───────┘└┘└───────┘└┘└─────────────────┘└─
doc                  └─────────┘         └┘         └┘                   └─
txt                  └─────────┘         └┘         └┘                   └─
par                  └─────────┘         └┘         └┘                   └─
pid                      └──┘└┘         └┘         └┘                   └─
st                  └──────────────────────────────────────────────────────
588    imp_and_distrib, and_iff_left id]
id     └─────────────┘  └──────────┘ └┘
src  ─┘└─────────────┘└┘└──────────┘└┘└─
typ  ─┘└─────────────┘└┘└──────────┘└┘└─
doc  ─┘               └┘              └─
txt  ─┘               └┘              └─
par  ─┘               └┘              └─
pid  ─┘               └┘              
st   ────────────────────────────────────
589  
src  
typ  
doc  
txt  
par  
pid  
st   
590  @[simp] theorem sdiff_union_self_eq_union {s t : finset α} : (s \ t) ∪ t = s ∪ t :=
id                                                    └────┘               
src                                                   └────┘                   
typ                                                   └────┘               
doc    └──┘                                           └────┘
591  by rw [union_comm, union_sdiff_self_eq_union, union_comm]
id          └────────┘  └───────────────────────┘  └────────┘
src     └──┘└────────┘└┘└───────────────────────┘└┘└────────┘└─
typ     └──┘└────────┘└┘└───────────────────────┘└┘└────────┘└─
doc     └──┘          └┘                         └┘          └─
txt     └──┘          └┘                         └┘          └─
par     └──┘          └┘                         └┘          └─
pid       └┘          └┘                         └┘          
st     └─────────────┘└─────────────────────────┘└──────────┘
592  
src  
typ  
doc  
txt  
par  
pid  
st   
593  lemma union_sdiff_symm {s t : finset α} : s ∪ (t \ s) = t ∪ (s \ t) :=
id                                 └────┘                  
src                                └────┘                       
typ                                └────┘                  
doc                                └────┘
594  by rw [union_sdiff_self_eq_union, union_sdiff_self_eq_union, union_comm]
id          └───────────────────────┘  └───────────────────────┘  └────────┘
src     └──┘└───────────────────────┘└┘└───────────────────────┘└┘└────────┘└─
typ     └──┘└───────────────────────┘└┘└───────────────────────┘└┘└────────┘└─
doc     └──┘                         └┘                         └┘          └─
txt     └──┘                         └┘                         └┘          └─
par     └──┘                         └┘                         └┘          └─
pid       └┘                         └┘                         └┘          
st     └────────────────────────────┘└─────────────────────────┘└──────────┘
595  
src  
typ  
doc  
txt  
par  
pid  
st   
596  lemma sdiff_eq_empty_iff_subset {s t : finset α} : s \ t = ∅ ↔ s ⊆ t :=
id                                          └────┘             
src                                         └────┘                
typ                                         └────┘             
doc                                         └────┘
597  by rw [subset_iff, ext]; simp
id          └────────┘  └─┘
src     └──┘└────────┘└┘└─┘  └────
typ     └──┘└────────┘└┘└─┘  └────
doc     └──┘          └┘     └────
txt     └──┘          └┘     └────
par     └──┘          └┘     └────
pid       └┘          └┘         
st     └─────────────┘└───┘└──────
598  
src  
typ  
doc  
txt  
par  
pid  
st   
599  @[simp] lemma empty_sdiff (s : finset α) : ∅ \ s = ∅ :=
id                                  └────┘         
src                                 └────┘           
typ                                 └────┘         
doc    └──┘                         └────┘
600  by { rw sdiff_eq_empty_iff_subset, exact empty_subset _ }
id           └───────────────────────┘        └──────────┘
src       └─┘└───────────────────────┘  └────┘└──────────┘└─┘
typ       └─┘└───────────────────────┘  └────┘└──────────┘└─┘
doc       └─┘                           └────┘            └─┘
txt       └─┘                           └────┘            └─┘
par       └─┘                           └────┘            └─┘
pid                                                     └┘
st     └─────────────────────────────┘└─────────────────────┘└┘
601  
602  lemma insert_sdiff_of_not_mem (s : finset α) {t : finset α} {x : α} (h : x ∉ t) :
id                                      └────┘        └────┘                 
src                                     └────┘         └────┘                   
typ                                     └────┘        └────┘                 
doc                                     └────┘         └────┘
603    (insert x s) \ t = insert x (s \ t) :=
id      └────┘       └────┘     
src     └────┘          └────┘      
typ     └────┘       └────┘     
604  begin
st   └─────
605    rw [← coe_inj, coe_insert, coe_sdiff, coe_sdiff, coe_insert],
id           └─────┘  └────────┘  └───────┘  └───────┘  └────────┘
src    └────┘└─────┘└┘└────────┘└┘└───────┘└┘└───────┘└┘└────────┘
typ    └────┘└─────┘└┘└────────┘└┘└───────┘└┘└───────┘└┘└────────┘
doc    └────┘       └┘          └┘         └┘         └┘          
txt    └────┘       └┘          └┘         └┘         └┘          
par    └────┘       └┘          └┘         └┘         └┘          
pid      └──┘       └┘          └┘         └┘         └┘          
st   ──────────────┘└──────────┘└─────────┘└─────────┘└──────────┘└──
606    exact set.insert_diff_of_not_mem ↑s h
id           └────────────────────────┘  
src    └────┘└────────────────────────┘  
typ    └────┘└────────────────────────┘
doc    └────┘                             
txt    └────┘                             
par    └────┘                             
pid                                      
st   ───────────────────────────────────────┘
607  end
st   └─┘
608  
609  lemma insert_sdiff_of_mem (s : finset α) {t : finset α} {x : α} (h : x ∈ t) :
id                                  └────┘        └────┘                 
src                                 └────┘         └────┘                   
typ                                 └────┘        └────┘                 
doc                                 └────┘         └────┘
610    (insert x s) \ t = s \ t :=
id      └────┘         
src     └────┘            
typ     └────┘         
611  begin
st   └─────
612    rw [← coe_inj, coe_sdiff, coe_sdiff, coe_insert],
id           └─────┘  └───────┘  └───────┘  └────────┘
src    └────┘└─────┘└┘└───────┘└┘└───────┘└┘└────────┘
typ    └────┘└─────┘└┘└───────┘└┘└───────┘└┘└────────┘
doc    └────┘       └┘         └┘         └┘          
txt    └────┘       └┘         └┘         └┘          
par    └────┘       └┘         └┘         └┘          
pid      └──┘       └┘         └┘         └┘          
st   ──────────────┘└─────────┘└─────────┘└──────────┘└──
613    exact set.insert_diff_of_mem ↑s h
id           └────────────────────┘  
src    └────┘└────────────────────┘  
typ    └────┘└────────────────────┘
doc    └────┘                         
txt    └────┘                         
par    └────┘                         
pid                                  
st   ───────────────────────────────────┘
614  end
st   └─┘
615  
616  end decidable_eq
617  
618  /-! ### attach -/
619  
620  /-- `attach s` takes the elements of `s` and forms a new set of elements of the
621    subtype `{x // x ∈ s}`. -/
622  def attach (s : finset α) : finset {x // x ∈ s} := ⟨attach s.1, nodup_attach.2 s.2⟩
id                   └────┘     └────┘             └────┘    └──────────┘  
src                  └────┘      └────┘                └────┘     └──────────┘   
typ                  └────┘     └────┘             └────┘    └──────────┘  
doc                  └────┘      └────┘                  └────┘
623  
624  @[simp] theorem attach_val (s : finset α) : s.attach.1 = s.1.attach := rfl
id                                   └────┘     └─────┘    └────┘     └─┘
src                                  └────┘       └─────┘     └────┘     └─┘
typ                                  └────┘     └─────┘    └────┘     └─┘
doc    └──┘                          └────┘       └─────┘        └────┘
625  
626  @[simp] theorem mem_attach (s : finset α) : ∀ x, x ∈ s.attach := mem_attach _
id                                   └────┘           └─────┘    └────────┘
src                                  └────┘               └─────┘    └────────┘
typ                                  └────┘           └─────┘    └────────┘
doc    └──┘                          └────┘                └─────┘
627  
628  @[simp] theorem attach_empty : attach (∅ : finset α) = ∅ := rfl
id                                  └────┘     └────┘        └─┘
src                                 └────┘     └────┘         └─┘
typ                                 └────┘     └────┘        └─┘
doc    └──┘                         └────┘      └────┘
629  
630  /-! ### piecewise -/
631  section piecewise
632  
633  /-- `s.piecewise f g` is the function equal to `f` on the finset `s`, and to `g` on its complement. -/
634  def piecewise {α : Type*} {δ : α → Sort*} (s : finset α) (f g : Πi, δ i) [∀j, decidable (j ∈ s)] :
id                                                 └────┘                    └───────┘    
src                                                 └────┘                         └───────┘    
typ                                                └────┘                    └───────┘    
doc                                                 └────┘
635    Πi, δ i :=
id         
typ        
636  λi, if i ∈ s then f i else g i
id                         
src           
typ                        
637  
638  variables {δ : α → Sort*} (s : finset α) (f g : Πi, δ i)
id                                  └────┘                
src                                 └────┘
typ                                 └────┘                
doc                                 └────┘
639  
640  @[simp] lemma piecewise_insert_self [decidable_eq α] {j : α} [∀i, decidable (i ∈ insert j s)] :
id                                        └──────────┘              └───────┘    └────┘  
src                                       └──────────┘                 └───────┘     └────┘
typ                                       └──────────┘              └───────┘    └────┘  
doc    └──┘
641    (insert j s).piecewise f g j = f j :=
id      └────┘   └───────┘       
src     └────┘     └───────┘        
typ     └────┘   └───────┘       
doc                └───────┘
642  by simp [piecewise]
id            └───────┘
src     └────┘└───────┘└─
typ     └────┘└───────┘└─
doc     └────┘└───────┘└─
txt     └────┘         └─
par     └────┘         └─
pid                  
st     └─────────────────
643  
src  
typ  
doc  
txt  
par  
pid  
st   
644  @[simp] lemma piecewise_empty [∀i : α, decidable (i ∈ (∅ : finset α))] : piecewise ∅ f g = g :=
id                                         └───────┘        └────┘       └───────┘     
src                                         └───────┘         └────┘        └───────┘      
typ                                        └───────┘        └────┘       └───────┘     
doc    └──┘                                                     └────┘        └───────┘
645  by { ext i, simp [piecewise] }
id                     └───────┘
src       └───┘  └────┘└───────┘└┘
typ       └───┘  └────┘└───────┘└┘
doc       └───┘  └────┘└───────┘└┘
txt       └───┘  └────┘         └┘
par       └───┘  └────┘         └┘
pid          └┘               
st     └──────┘└─────────────────┘└┘
646  
647  variable [∀j, decidable (j ∈ s)]
id                └───────┘   
src                └───────┘    
typ               └───────┘   
648  
649  @[elim_cast] lemma piecewise_coe [∀j, decidable (j ∈ (↑s : set α))] :
id                                        └───────┘        └─┘ 
src                                        └───────┘          └─┘
typ                                       └───────┘        └─┘ 
doc    └───────┘
650    (↑s : set α).piecewise f g = s.piecewise f g :=
id         └─┘  └───────┘     └────────┘  
src         └─┘   └───────┘        └────────┘
typ        └─┘  └───────┘     └────────┘  
doc                └───────┘         └────────┘
651  by { ext, congr }
src       └─┘  └────┘
typ       └─┘  └────┘
doc       └─┘
txt       └─┘  └────┘
par       └─┘  └────┘
pid                 
st     └────┘└──────┘└┘
652  
653  @[simp] lemma piecewise_eq_of_mem {i : α} (hi : i ∈ s) : s.piecewise f g i = f i :=
id                                                        └────────┘      
src                                                           └────────┘       
typ                                                       └────────┘      
doc    └──┘                                                    └────────┘
654  by simp [piecewise, hi]
id            └───────┘  └┘
src     └────┘└───────┘└┘  └─
typ     └────┘└───────┘└┘└┘└─
doc     └────┘└───────┘└┘  └─
txt     └────┘         └┘  └─
par     └────┘         └┘  └─
pid                  └┘  
st     └─────────────────────
655  
src  
typ  
doc  
txt  
par  
pid  
st   
656  @[simp] lemma piecewise_eq_of_not_mem {i : α} (hi : i ∉ s) : s.piecewise f g i = g i :=
id                                                            └────────┘      
src                                                               └────────┘       
typ                                                           └────────┘      
doc    └──┘                                                        └────────┘
657  by simp [piecewise, hi]
id            └───────┘  └┘
src     └────┘└───────┘└┘  └─
typ     └────┘└───────┘└┘└┘└─
doc     └────┘└───────┘└┘  └─
txt     └────┘         └┘  └─
par     └────┘         └┘  └─
pid                  └┘  
st     └─────────────────────
658  
src  
typ  
doc  
txt  
par  
pid  
st   
659  @[simp] lemma piecewise_insert_of_ne [decidable_eq α] {i j : α} [∀i, decidable (i ∈ insert j s)]
id                                         └──────────┘                └───────┘    └────┘  
src                                        └──────────┘                   └───────┘     └────┘
typ                                        └──────────┘                └───────┘    └────┘  
doc    └──┘
660    (h : i ≠ j) : (insert j s).piecewise f g i = s.piecewise f g i :=
id                 └────┘   └───────┘      └────────┘   
src                  └────┘     └───────┘          └────────┘
typ                └────┘   └───────┘      └────────┘   
doc                              └───────┘           └────────┘
661  by { simp [piecewise, h], congr }
id              └───────┘  
src       └────┘└───────┘└┘   └────┘
typ       └────┘└───────┘└┘  └────┘
doc       └────┘└───────┘└┘ 
txt       └────┘         └┘   └────┘
par       └────┘         └┘   └────┘
pid                    └┘        
st     └────────────────────┘└──────┘└┘
662  
663  lemma piecewise_insert [decidable_eq α] (j : α) [∀i, decidable (i ∈ insert j s)] :
id                           └──────────┘              └───────┘    └────┘  
src                          └──────────┘                 └───────┘     └────┘
typ                          └──────────┘              └───────┘    └────┘  
664    (insert j s).piecewise f g = function.update (s.piecewise f g) j (f j) :=
id      └────┘   └───────┘     └─────────────┘  └────────┘       
src     └────┘     └───────┘       └─────────────┘   └────────┘
typ     └────┘   └───────┘     └─────────────┘  └────────┘       
doc                └───────┘        └─────────────┘   └────────┘
665  begin
st   └─────
666    classical,
src    └───────┘
typ    └───────┘
doc    └───────┘
txt    └───────┘
par    └───────┘
st   ──────────┘└─
667    rw [← piecewise_coe, ← piecewise_coe, ← set.piecewise_insert, ← coe_insert j s],
id           └───────────┘    └───────────┘    └──────────────────┘    └────────┘  
src    └────┘└───────────┘└──┘└───────────┘└──┘└──────────────────┘└──┘└────────┘  
typ    └────┘└───────────┘└──┘└───────────┘└──┘└──────────────────┘└──┘└────────┘
doc    └────┘             └──┘             └──┘                    └──┘            
txt    └────┘             └──┘             └──┘                    └──┘            
par    └────┘             └──┘             └──┘                    └──┘            
pid      └──┘             └──┘             └──┘                    └──┘            
st   ────────────────────┘└───────────────┘└──────────────────────┘└────────────────┘└──
668    congr
src    └────┘
typ    └────┘
txt    └────┘
par    └────┘
pid         
st   ───────┘
669  end
st   └─┘
670  
671  lemma update_eq_piecewise {β : Type*} [decidable_eq α] (f : α → β) (i : α) (v : β) :
id                                          └──────────┘                         
src                                         └──────────┘
typ                                         └──────────┘                         
672    function.update f i v = piecewise (singleton i) (λj, v) f :=
id     └─────────────┘     └───────┘  └───────┘         
src    └─────────────┘        └───────┘  └───────┘
typ    └─────────────┘     └───────┘  └───────┘         
doc    └─────────────┘         └───────┘  └───────┘
673  begin
st   └─────
674    ext j,
src    └───┘
typ    └───┘
doc    └───┘
txt    └───┘
par    └───┘
pid       └┘
st   ──────┘└─
675    by_cases h : j = i,
id                    
src    └───────┘ └─┘ 
typ    └───────┘ └─┘
doc    └───────┘ └─┘  
txt    └───────┘ └─┘  
par    └───────┘ └─┘  
pid             └─┘  
st   ───────────────────┘└─
676    { rw [h], simp },
id           
src      └──┘   └───┘
typ      └──┘  └───┘
doc      └──┘   └───┘
txt      └──┘   └───┘
par      └──┘   └───┘
pid        └┘       
st   ───┘└───┘└──────┘└┘
677    { simp [h] }
id             
src      └────┘ └┘
typ      └────┘└┘
doc      └────┘ └┘
txt      └────┘ └┘
par      └────┘ └┘
pid           
st   ────────────┘└─
678  end
st   ──┘
679  
680  end piecewise
681  
682  section decidable_pi_exists
683  variables {s : finset α}
id                  └────┘
src                 └────┘
typ                 └────┘
doc                 └────┘
684  
685  instance decidable_dforall_finset {p : Πa∈s, Prop} [hp : ∀a (h : a ∈ s), decidable (p a h)] :
id                                                                      └───────┘    
src                                                                          └───────┘
typ                                                                     └───────┘    
686    decidable (∀a (h : a ∈ s), p a h) :=
id     └───────┘                
src    └───────┘            
typ    └───────┘                
687  multiset.decidable_dforall_multiset
id   └─────────────────────────────────┘
src  └─────────────────────────────────┘
typ  └─────────────────────────────────┘
688  
689  /-- decidable equality for functions whose domain is bounded by finsets -/
690  instance decidable_eq_pi_finset {β : α → Type*} [h : ∀a, decidable_eq (β a)] :
id                                                          └──────────┘   
src                                                           └──────────┘
typ                                                         └──────────┘   
691    decidable_eq (Πa∈s, β a) :=
id     └──────────┘       
src    └──────────┘
typ    └──────────┘       
692  multiset.decidable_eq_pi_multiset
id   └───────────────────────────────┘
src  └───────────────────────────────┘
typ  └───────────────────────────────┘
doc  └───────────────────────────────┘
693  
694  instance decidable_dexists_finset {p : Πa∈s, Prop} [hp : ∀a (h : a ∈ s), decidable (p a h)] :
id                                                                      └───────┘    
src                                                                          └───────┘
typ                                                                     └───────┘    
695    decidable (∃a (h : a ∈ s), p a h) :=
id     └───────┘              
src    └───────┘              
typ    └───────┘              
696  multiset.decidable_dexists_multiset
id   └─────────────────────────────────┘
src  └─────────────────────────────────┘
typ  └─────────────────────────────────┘
697  
698  end decidable_pi_exists
699  
700  /-! ### filter -/
701  section filter
702  variables {p q : α → Prop} [decidable_pred p] [decidable_pred q]
id                              └────────────┘     └────────────┘
src                              └────────────┘     └────────────┘
typ                             └────────────┘     └────────────┘
703  
704  /-- `filter p s` is the set of elements of `s` that satisfy `p`. -/
705  def filter (p : α → Prop) [decidable_pred p] (s : finset α) : finset α :=
id                             └────────────┘        └────┘     └────┘ 
src                             └────────────┘         └────┘      └────┘
typ                            └────────────┘        └────┘     └────┘ 
doc                                                    └────┘      └────┘
706  ⟨_, nodup_filter p s.2⟩
id       └──────────┘  
src      └──────────┘    
typ      └──────────┘  
707  
708  @[simp] theorem filter_val (s : finset α) : (filter p s).1 = s.1.filter p := rfl
id                                   └────┘      └────┘       └────┘      └─┘
src                                  └────┘       └────┘          └────┘       └─┘
typ                                  └────┘      └────┘       └────┘      └─┘
doc    └──┘                          └────┘       └────┘             └────┘
709  
710  @[simp] theorem mem_filter {s : finset α} {a : α} : a ∈ s.filter p ↔ a ∈ s ∧ p a := mem_filter
id                                   └────┘              └─────┘            └────────┘
src                                  └────┘                  └─────┘                 └────────┘
typ                                  └────┘              └─────┘            └────────┘
doc    └──┘                          └────┘                   └─────┘
711  
712  @[simp] theorem filter_subset (s : finset α) : s.filter p ⊆ s := filter_subset _
id                                      └────┘     └─────┘       └───────────┘
src                                     └────┘       └─────┘         └───────────┘
typ                                     └────┘     └─────┘       └───────────┘
doc    └──┘                             └────┘       └─────┘
713  
714  theorem filter_filter (s : finset α) :
id                              └────┘ 
src                             └────┘
typ                             └────┘ 
doc                             └────┘
715    (s.filter p).filter q = s.filter (λa, p a ∧ q a) :=
id      └─────┘  └────┘    └─────┘         
src      └─────┘   └────┘      └─────┘          
typ     └─────┘  └────┘    └─────┘         
doc      └─────┘   └────┘       └─────┘
716  ext.2 $ assume a, by simp only [mem_filter, and_comm, and.left_comm]
id   └─┘                           └────────┘  └──────┘  └───────────┘
src  └─┘                 └─────────┘└────────┘└┘└──────┘└┘└───────────┘└─
typ  └─┘                └─────────┘└────────┘└┘└──────┘└┘└───────────┘└─
doc                       └─────────┘          └┘        └┘             └─
txt                       └─────────┘          └┘        └┘             └─
par                       └─────────┘          └┘        └┘             └─
pid                           └──┘└┘          └┘        └┘             
st                       └────────────────────────────────────────────────
717  
src  
typ  
doc  
txt  
par  
pid  
st   
718  @[simp] lemma filter_true {s : finset α} [h : decidable_pred (λ _, true)] :
id                                  └────┘        └────────────┘      └──┘
src                                 └────┘         └────────────┘       └──┘
typ                                 └────┘        └────────────┘      └──┘
doc    └──┘                         └────┘
719    @finset.filter α (λ _, true) h s = s :=
id      └───────────┘       └──┘     
src     └───────────┘         └──┘      
typ     └───────────┘       └──┘     
doc     └───────────┘
720  by ext; simp
src     └─┘  └────
typ     └─┘  └────
doc     └─┘  └────
txt     └─┘  └────
par     └─┘  └────
pid              
st     └──────────
721  
src  
typ  
doc  
txt  
par  
pid  
st   
722  @[simp] theorem filter_false {h} (s : finset α) : @filter α (λa, false) h s = ∅ :=
id                                         └────┘      └────┘      └───┘     
src                                        └────┘       └────┘        └───┘       
typ                                        └────┘      └────┘      └───┘     
doc    └──┘                                └────┘       └────┘
723  ext.2 $ assume a, by simp only [mem_filter, and_false]; refl
id   └─┘                           └────────┘  └───────┘
src  └─┘                 └─────────┘└────────┘└┘└───────┘  └────
typ  └─┘                └─────────┘└────────┘└┘└───────┘  └────
doc                       └─────────┘          └┘           └────
txt                       └─────────┘          └┘           └────
par                       └─────────┘          └┘           └────
pid                           └──┘└┘          └┘               
st                       └────────────────────────────────────────
724  
src  
typ  
doc  
txt  
par  
pid  
st   
725  lemma filter_congr {s : finset α} (H : ∀ x ∈ s, p x ↔ q x) : filter p s = filter q s :=
id                           └────┘                       └────┘    └────┘  
src                          └────┘                              └────┘      └────┘
typ                          └────┘                       └────┘    └────┘  
doc                          └────┘                               └────┘       └────┘
726  eq_of_veq $ filter_congr H
id   └───────┘   └──────────┘ 
src  └───────┘   └──────────┘
typ  └───────┘   └──────────┘ 
727  
728  lemma filter_empty : filter p ∅ = ∅ :=
id                        └────┘    
src                       └────┘     
typ                       └────┘    
doc                       └────┘
729  subset_empty.1 $ filter_subset _
id   └──────────┘    └───────────┘
src  └──────────┘    └───────────┘
typ  └──────────┘    └───────────┘
730  
731  lemma filter_subset_filter {s t : finset α} (h : s ⊆ t) : s.filter p ⊆ t.filter p :=
id                                     └────┘              └─────┘   └─────┘ 
src                                    └────┘                  └─────┘     └─────┘
typ                                    └────┘              └─────┘   └─────┘ 
doc                                    └────┘                   └─────┘      └─────┘
732  assume a ha, mem_filter.2 ⟨h (mem_filter.1 ha).1, (mem_filter.1 ha).2⟩
id           └┘  └────────┘     └────────┘  └┘     └────────┘  └┘ 
src               └────────┘      └────────┘         └────────┘     
typ          └┘  └────────┘     └────────┘  └┘     └────────┘  └┘ 
733  
734  @[simp] lemma coe_filter (s : finset α) : ↑(s.filter p) = ({x ∈ ↑s | p x} : set α) :=
id                                 └────┘      └─────┘                 └─┘ 
src                                └────┘        └─────┘                     └─┘
typ                                └────┘      └─────┘                 └─┘ 
doc    └──┘                        └────┘         └─────┘
735  set.ext $ λ _, mem_filter
id   └─────┘       └────────┘
src  └─────┘        └────────┘
typ  └─────┘       └────────┘
736  
737  variable [decidable_eq α]
id             └──────────┘
src            └──────────┘
typ            └──────────┘
738  theorem filter_union (s₁ s₂ : finset α) :
id                                 └────┘ 
src                                └────┘
typ                                └────┘ 
doc                                └────┘
739    (s₁ ∪ s₂).filter p = s₁.filter p ∪ s₂.filter p :=
id      └┘  └┘ └────┘    └┘└─────┘   └┘└─────┘ 
src            └────┘       └─────┘      └─────┘
typ     └┘  └┘ └────┘    └┘└─────┘   └┘└─────┘ 
doc             └────┘        └─────┘       └─────┘
740  ext.2 $ λ _, by simp only [mem_filter, mem_union, or_and_distrib_right]
id   └─┘                      └────────┘  └───────┘  └──────────────────┘
src  └─┘            └─────────┘└────────┘└┘└───────┘└┘└──────────────────┘└─
typ  └─┘           └─────────┘└────────┘└┘└───────┘└┘└──────────────────┘└─
doc                  └─────────┘          └┘         └┘                    └─
txt                  └─────────┘          └┘         └┘                    └─
par                  └─────────┘          └┘         └┘                    └─
pid                      └──┘└┘          └┘         └┘                    
st                  └────────────────────────────────────────────────────────
741  
src  
typ  
doc  
txt  
par  
pid  
st   
742  theorem filter_union_right (p q : α → Prop) [decidable_pred p] [decidable_pred q] (s : finset α) :
id                                               └────────────┘    └────────────┘        └────┘ 
src                                               └────────────┘     └────────────┘         └────┘
typ                                              └────────────┘    └────────────┘        └────┘ 
doc                                                                                         └────┘
743    s.filter p ∪ s.filter q = s.filter (λx, p x ∨ q x) :=
id     └─────┘   └─────┘   └─────┘         
src     └─────┘     └─────┘     └─────┘          
typ    └─────┘   └─────┘   └─────┘         
doc     └─────┘      └─────┘      └─────┘
744  ext.2 $ λ x, by simp only [mem_filter, mem_union, and_or_distrib_left.symm]
id   └─┘                      └────────┘  └───────┘
src  └─┘            └─────────┘└────────┘└┘└───────┘└┘                        └─
typ  └─┘           └─────────┘└────────┘└┘└───────┘└┘└──────────────────────┘└─
doc                  └─────────┘          └┘         └┘                        └─
txt                  └─────────┘          └┘         └┘                        └─
par                  └─────────┘          └┘         └┘                        └─
pid                      └──┘└┘          └┘         └┘                        
st                  └────────────────────────────────────────────────────────────
745  
src  
typ  
doc  
txt  
par  
pid  
st   
746  lemma filter_mem_eq_inter {s t : finset α} : s.filter (λ i, i ∈ t) = s ∩ t :=
id                                    └────┘     └─────┘             
src                                   └────┘       └─────┘                
typ                                   └────┘     └─────┘             
doc                                   └────┘       └─────┘
747  ext' $ λ i, by rw [mem_filter, mem_inter]
id   └──┘              └────────┘  └───────┘
src  └──┘           └──┘└────────┘└┘└───────┘└─
typ  └──┘          └──┘└────────┘└┘└───────┘└─
doc                 └──┘          └┘         └─
txt                 └──┘          └┘         └─
par                 └──┘          └┘         └─
pid                   └┘          └┘         
st                 └─────────────┘└─────────┘
748  
src  
typ  
doc  
txt  
par  
pid  
st   
749  theorem filter_inter {s t : finset α} : filter p s ∩ t = filter p (s ∩ t) :=
id                               └────┘     └────┘      └────┘     
src                              └────┘      └────┘         └────┘      
typ                              └────┘     └────┘      └────┘     
doc                              └────┘      └────┘           └────┘
750  by { ext, simp only [mem_inter, mem_filter, and.right_comm] }
id                        └───────┘  └────────┘  └────────────┘
src       └─┘  └─────────┘└───────┘└┘└────────┘└┘└────────────┘└┘
typ       └─┘  └─────────┘└───────┘└┘└────────┘└┘└────────────┘└┘
doc       └─┘  └─────────┘         └┘          └┘              └┘
txt       └─┘  └─────────┘         └┘          └┘              └┘
par       └─┘  └─────────┘         └┘          └┘              └┘
pid                └──┘└┘         └┘          └┘              
st     └────┘└──────────────────────────────────────────────────┘└┘
751  
752  theorem inter_filter {s t : finset α} : s ∩ filter p t = filter p (s ∩ t) :=
id                               └────┘       └────┘    └────┘     
src                              └────┘         └────┘      └────┘      
typ                              └────┘       └────┘    └────┘     
doc                              └────┘          └────┘       └────┘
753  by rw [inter_comm, filter_inter, inter_comm]
id          └────────┘  └──────────┘  └────────┘
src     └──┘└────────┘└┘└──────────┘└┘└────────┘└─
typ     └──┘└────────┘└┘└──────────┘└┘└────────┘└─
doc     └──┘          └┘            └┘          └─
txt     └──┘          └┘            └┘          └─
par     └──┘          └┘            └┘          └─
pid       └┘          └┘            └┘          
st     └─────────────┘└────────────┘└──────────┘
754  
src  
typ  
doc  
txt  
par  
pid  
st   
755  theorem filter_insert (a : α) (s : finset α) :
id                                     └────┘ 
src                                     └────┘
typ                                    └────┘ 
doc                                     └────┘
756    filter p (insert a s) = if p a then insert a (filter p s) else (filter p s) :=
id     └────┘   └────┘               └────┘   └────┘          └────┘  
src    └────┘    └────┘                   └────┘    └────┘            └────┘
typ    └────┘   └────┘               └────┘   └────┘          └────┘  
doc    └────┘                                        └────┘            └────┘
757  by { ext x, simp, split_ifs with h; by_cases h' : x = a; simp [h, h'] }
id                                                                 └┘
src       └───┘  └──┘  └──────────────┘  └───────┘  └─┘    └────┘ └┘  └┘
typ       └───┘  └──┘  └──────────────┘  └───────┘  └─┘  └────┘└┘└┘└┘
doc       └───┘  └──┘  └──────────────┘  └───────┘  └─┘     └────┘ └┘  └┘
txt       └───┘  └──┘  └──────────────┘  └───────┘  └─┘     └────┘ └┘  └┘
par       └───┘  └──┘  └──────────────┘  └───────┘  └─┘     └────┘ └┘  └┘
pid          └┘                 └────┘            └─┘          └┘  
st     └──────┘└────┘└────────────────────────────────────────────────────┘└┘
758  
759  theorem filter_singleton (a : α) : filter p (singleton a) = if p a then singleton a else ∅ :=
id                                     └────┘   └───────┘              └───────┘       
src                                     └────┘    └───────┘                 └───────┘        
typ                                    └────┘   └───────┘              └───────┘       
doc                                     └────┘    └───────┘                  └───────┘
760  by { ext x, simp, split_ifs with h; by_cases h' : x = a; simp [h, h'] }
id                                                                 └┘
src       └───┘  └──┘  └──────────────┘  └───────┘  └─┘    └────┘ └┘  └┘
typ       └───┘  └──┘  └──────────────┘  └───────┘  └─┘  └────┘└┘└┘└┘
doc       └───┘  └──┘  └──────────────┘  └───────┘  └─┘     └────┘ └┘  └┘
txt       └───┘  └──┘  └──────────────┘  └───────┘  └─┘     └────┘ └┘  └┘
par       └───┘  └──┘  └──────────────┘  └───────┘  └─┘     └────┘ └┘  └┘
pid          └┘                 └────┘            └─┘          └┘  
st     └──────┘└────┘└────────────────────────────────────────────────────┘└┘
761  
762  theorem filter_or (s : finset α) : s.filter (λ a, p a ∨ q a) = s.filter p ∪ s.filter q :=
id                          └────┘     └─────┘             └─────┘   └─────┘ 
src                         └────┘       └─────┘                   └─────┘     └─────┘
typ                         └────┘     └─────┘             └─────┘   └─────┘ 
doc                         └────┘       └─────┘                     └─────┘      └─────┘
763  ext.2 $ λ _, by simp only [mem_filter, mem_union, and_or_distrib_left]
id   └─┘                      └────────┘  └───────┘  └─────────────────┘
src  └─┘            └─────────┘└────────┘└┘└───────┘└┘└─────────────────┘└─
typ  └─┘           └─────────┘└────────┘└┘└───────┘└┘└─────────────────┘└─
doc                  └─────────┘          └┘         └┘                   └─
txt                  └─────────┘          └┘         └┘                   └─
par                  └─────────┘          └┘         └┘                   └─
pid                      └──┘└┘          └┘         └┘                   
st                  └───────────────────────────────────────────────────────
764  
src  
typ  
doc  
txt  
par  
pid  
st   
765  theorem filter_and (s : finset α) : s.filter (λ a, p a ∧ q a) = s.filter p ∩ s.filter q :=
id                           └────┘     └─────┘             └─────┘   └─────┘ 
src                          └────┘       └─────┘                   └─────┘     └─────┘
typ                          └────┘     └─────┘             └─────┘   └─────┘ 
doc                          └────┘       └─────┘                     └─────┘      └─────┘
766  ext.2 $ λ _, by simp only [mem_filter, mem_inter, and_comm, and.left_comm, and_self]
id   └─┘                      └────────┘  └───────┘  └──────┘  └───────────┘  └──────┘
src  └─┘            └─────────┘└────────┘└┘└───────┘└┘└──────┘└┘└───────────┘└┘└──────┘└─
typ  └─┘           └─────────┘└────────┘└┘└───────┘└┘└──────┘└┘└───────────┘└┘└──────┘└─
doc                  └─────────┘          └┘         └┘        └┘             └┘        └─
txt                  └─────────┘          └┘         └┘        └┘             └┘        └─
par                  └─────────┘          └┘         └┘        └┘             └┘        └─
pid                      └──┘└┘          └┘         └┘        └┘             └┘        
st                  └─────────────────────────────────────────────────────────────────────
767  
src  
typ  
doc  
txt  
par  
pid  
st   
768  theorem filter_not (s : finset α) : s.filter (λ a, ¬ p a) = s \ s.filter p :=
id                           └────┘     └─────┘             └─────┘ 
src                          └────┘       └─────┘                  └─────┘
typ                          └────┘     └─────┘             └─────┘ 
doc                          └────┘       └─────┘                     └─────┘
769  ext.2 $ by simpa only [mem_filter, mem_sdiff, and_comm, not_and] using λ a, and_congr_right $
id   └─┘                   └────────┘  └───────┘  └──────┘  └─────┘             └─────────────┘
src  └─┘       └──────────┘└────────┘└┘└───────┘└┘└──────┘└┘└─────┘└──────┘ └──┘└─────────────┘ 
typ  └─┘       └──────────┘└────────┘└┘└───────┘└┘└──────┘└┘└─────┘└──────┘ └──┘└─────────────┘ 
doc             └──────────┘          └┘         └┘        └┘       └──────┘ └──┘                
txt             └──────────┘          └┘         └┘        └┘       └──────┘ └──┘                
par             └──────────┘          └┘         └┘        └┘       └──────┘ └──┘                
pid                  └──┘└┘          └┘         └┘        └┘       └────┘ └──┘                
st             └───────────────────────────────────────────────────────────────────────────────────
770    λ h : a ∈ s, (imp_iff_right h).symm.trans imp_not_comm
id                 └───────────┘               └──────────┘
src  ─┘ └───┘  └┘ └───────────┘ └───────────┘└──────────┘
typ  ─┘ └───┘ └┘ └───────────┘ └───────────┘└──────────┘
doc  ─┘ └───┘   └┘               └───────────┘            
txt  ─┘ └───┘   └┘               └───────────┘            
par  ─┘ └───┘   └┘               └───────────┘            
pid  ─┘ └───┘   └┘               └───────────┘            
st   ─────────────────────────────────────────────────────────
771  
src  
typ  
doc  
txt  
par  
pid  
st   
772  theorem sdiff_eq_filter (s₁ s₂ : finset α) :
id                                    └────┘ 
src                                   └────┘
typ                                   └────┘ 
doc                                   └────┘
773    s₁ \ s₂ = filter (∉ s₂) s₁ := ext.2 $ λ _, by simp only [mem_sdiff, mem_filter]
id     └┘  └┘  └────┘   └┘  └┘    └─┘                      └───────┘  └────────┘
src            └────┘             └─┘            └─────────┘└───────┘└┘└────────┘└─
typ    └┘  └┘  └────┘   └┘  └┘    └─┘           └─────────┘└───────┘└┘└────────┘└─
doc              └────┘                              └─────────┘         └┘          └─
txt                                                  └─────────┘         └┘          └─
par                                                  └─────────┘         └┘          └─
pid                                                      └──┘└┘         └┘          
st                                                  └──────────────────────────────────
774  
src  
typ  
doc  
txt  
par  
pid  
st   
775  theorem filter_union_filter_neg_eq (s : finset α) : s.filter p ∪ s.filter (λa, ¬ p a) = s :=
id                                           └────┘     └─────┘   └─────┘          
src                                          └────┘       └─────┘     └─────┘            
typ                                          └────┘     └─────┘   └─────┘          
doc                                          └────┘       └─────┘      └─────┘
776  by simp only [filter_not, union_sdiff_of_subset (filter_subset s)]
id                 └────────┘  └───────────────────┘  └───────────┘ 
src     └─────────┘└────────┘└┘└───────────────────┘ └───────────┘ └──
typ     └─────────┘└────────┘└┘└───────────────────┘ └───────────┘└──
doc     └─────────┘          └┘                                    └──
txt     └─────────┘          └┘                                    └──
par     └─────────┘          └┘                                    └──
pid         └──┘└┘          └┘                                    └┘
st     └────────────────────────────────────────────────────────────────
777  
src  
typ  
doc  
txt  
par  
pid  
st   
778  theorem filter_inter_filter_neg_eq (s : finset α) : s.filter p ∩ s.filter (λa, ¬ p a) = ∅ :=
id                                           └────┘     └─────┘   └─────┘          
src                                          └────┘       └─────┘     └─────┘             
typ                                          └────┘     └─────┘   └─────┘          
doc                                          └────┘       └─────┘      └─────┘
779  by simp only [filter_not, inter_sdiff_self]
id                 └────────┘  └──────────────┘
src     └─────────┘└────────┘└┘└──────────────┘└─
typ     └─────────┘└────────┘└┘└──────────────┘└─
doc     └─────────┘          └┘                └─
txt     └─────────┘          └┘                └─
par     └─────────┘          └┘                └─
pid         └──┘└┘          └┘                
st     └─────────────────────────────────────────
780  
src  
typ  
doc  
txt  
par  
pid  
st   
781  lemma subset_union_elim {s : finset α} {t₁ t₂ : set α} [decidable_pred (∈ t₁)] (h : ↑s ⊆ t₁ ∪ t₂) :
id                                └────┘            └─┘    └────────────┘   └┘          └┘  └┘
src                               └────┘             └─┘     └────────────┘                   
typ                               └────┘            └─┘    └────────────┘   └┘          └┘  └┘
doc                               └────┘
782    ∃s₁ s₂ : finset α, s₁ ∪ s₂ = s ∧ ↑s₁ ⊆ t₁ ∧ ↑s₂ ⊆ t₂ \ t₁ :=
id             └────┘  └┘  └┘    └┘  └┘  └┘  └┘  └┘
src            └────┘                             
typ            └────┘  └┘  └┘    └┘  └┘  └┘  └┘  └┘
doc             └────┘
783  begin
st   └─────
784    refine ⟨s.filter (∈ t₁), s.filter (∉ t₁), _, _ , _⟩,
id                             └──────┘   └┘
src    └─────┘         └┘  └─┘└──────┘└┘  └──────────┘
typ    └─────┘         └┘  └─┘└──────┘└┘└┘└──────────┘
doc    └─────┘          └┘  └─┘└──────┘ └┘  └──────────┘
txt    └─────┘          └┘  └─┘         └┘  └──────────┘
par    └─────┘          └┘  └─┘         └┘  └──────────┘
pid                    └┘  └─┘         └┘  └──────────┘
st   ────────────────────────────────────────────────────┘└─
785    { simp [filter_union_right, classical.or_not] },
id             └────────────────┘  └──────────────┘
src      └────┘└────────────────┘└┘└──────────────┘└┘
typ      └────┘└────────────────┘└┘└──────────────┘└┘
doc      └────┘                  └┘                └┘
txt      └────┘                  └┘                └┘
par      └────┘                  └┘                └┘
pid                            └┘                
st   ───┘└──────────────────────────────────────────┘└┘
786    { intro x, simp },
src      └─────┘  └───┘
typ      └─────┘  └───┘
doc      └─────┘  └───┘
txt      └─────┘  └───┘
par      └─────┘  └───┘
pid           └┘      
st   ───┘└─────┘└─────┘└┘
787    { intro x, simp, intros hx hx₂, refine ⟨or.resolve_left (h hx) hx₂, hx₂⟩ }
id                                             └─────────────┘   └┘       └─┘
src      └─────┘  └──┘  └───────────┘  └─────┘ └─────────────┘    └┘   └┘   └┘
typ      └─────┘  └──┘  └───────────┘  └─────┘ └─────────────┘ └┘└┘   └┘└─┘└┘
doc      └─────┘  └──┘  └───────────┘  └─────┘                    └┘   └┘   └┘
txt      └─────┘  └──┘  └───────────┘  └─────┘                    └┘   └┘   └┘
par      └─────┘  └──┘  └───────────┘  └─────┘                    └┘   └┘   └┘
pid           └┘              └─────┘                            └┘   └┘   
st   ──────────┘└────┘└─────────────┘└─────────────────────────────────────────┘└─
788  end
st   ──┘
789  
790  /- We can simplify an application of filter where the decidability is inferred in "the wrong way" -/
791  @[simp] lemma filter_congr_decidable {α} (s : finset α) (p : α → Prop) (h : decidable_pred p)
id                                                 └────┘                      └────────────┘ 
src                                                └────┘                        └────────────┘
typ                                                └────┘                      └────────────┘ 
doc    └──┘                                        └────┘
792    [decidable_pred p] : @filter α p h s = s.filter p :=
id      └────────────┘      └────┘      └─────┘ 
src     └────────────┘       └────┘           └─────┘
typ     └────────────┘      └────┘      └─────┘ 
doc                          └────┘            └─────┘
793  by congr
src     └─────
typ     └─────
txt     └─────
par     └─────
pid          
st     └──────
794  
src  
typ  
txt  
par  
pid  
st   
795  section classical
796  open_locale classical
797  /-- The following instance allows us to write `{ x ∈ s | p x }` for `finset.filter s p`.
798    Since the former notation requires us to define this for all propositions `p`, and `finset.filter`
799    only works for decidable propositions, the notation `{ x ∈ s | p x }` is only compatible with
800    classical logic because it uses `classical.prop_decidable`.
801    We don't want to redo all lemmas of `finset.filter` for `has_sep.sep`, so we make sure that `simp`
802    unfolds the notation `{ x ∈ s | p x }` to `finset.filter s p`. If `p` happens to be decidable, the
803    simp-lemma `filter_congr_decidable` will make sure that `finset.filter` uses the right instance
804    for decidability.
805  -/
806  noncomputable instance {α : Type*} : has_sep α (finset α) := ⟨λ p x, x.filter p⟩
id                                        └─────┘   └────┘            └─────┘ 
src                                       └─────┘    └────┘                └─────┘
typ                                       └─────┘   └────┘            └─────┘ 
doc                                                  └────┘                └─────┘
807  
808  @[simp] lemma sep_def {α : Type*} (s : finset α) (p : α → Prop) : {x ∈ s | p x} = s.filter p := rfl
id                                          └────┘                              └─────┘     └─┘
src                                         └────┘                                    └─────┘      └─┘
typ                                         └────┘                              └─────┘     └─┘
doc    └──┘                                 └────┘                                      └─────┘
809  
810  end classical
811  
812  /--
813    After filtering out everything that does not equal a given value, at most that value remains.
814  
815    This is equivalent to `filter_eq'` with the equality the other way.
816  -/
817  -- This is not a good simp lemma, as it would prevent `finset.mem_filter` from firing
818  -- on, e.g. `x ∈ s.filter(eq b)`.
819  lemma filter_eq [decidable_eq β] (s : finset β) (b : β) :
id                    └──────────┘        └────┘        
src                   └──────────┘         └────┘
typ                   └──────────┘        └────┘        
doc                                        └────┘
820    s.filter(eq b) = ite (b ∈ s) {b} ∅ :=
id     └─────┘ └┘    └─┘        
src     └─────┘ └┘     └─┘           
typ    └─────┘ └┘    └─┘        
doc     └─────┘
821  begin
st   └─────
822    split_ifs,
src    └───────┘
typ    └───────┘
doc    └───────┘
txt    └───────┘
par    └───────┘
st   ──────────┘└─
823    { ext,
src      └─┘
typ      └─┘
doc      └─┘
txt      └─┘
par      └─┘
st   ───┘└─┘└─
824      simp only [mem_filter, insert_empty_eq_singleton, mem_singleton],
id                  └────────┘  └───────────────────────┘  └───────────┘
src      └─────────┘└────────┘└┘└───────────────────────┘└┘└───────────┘
typ      └─────────┘└────────┘└┘└───────────────────────┘└┘└───────────┘
doc      └─────────┘          └┘                         └┘             
txt      └─────────┘          └┘                         └┘             
par      └─────────┘          └┘                         └┘             
pid          └──┘└┘          └┘                         └┘             
st   ───────────────────────────────────────────────────────────────────┘└─
825      exact ⟨λ h, h.2.symm, by { rintro ⟨h⟩, exact ⟨h, rfl⟩, }⟩ },
id                                                       └─┘
src      └────┘  └──┘ └───────┘  └─┘└────────┘└──────┘  └┘└─┘└────┘
typ      └────┘  └──┘ └───────┘  └─┘└────────┘└──────┘ └┘└─┘└────┘
doc      └────┘  └──┘ └───────┘  └─┘└────────┘└──────┘  └┘   └────┘
txt      └────┘  └──┘ └───────┘  └─┘└────────┘└──────┘  └┘   └────┘
par      └────┘  └──┘ └───────┘  └─┘└────────┘└──────┘  └┘   └────┘
pid             └──┘ └───────┘  └───────────────────┘  └┘   └───┘
st   ───────────────────────────┘└───────────┘└──────────────┘└─┘└┘└┘
826    { ext,
src      └─┘
typ      └─┘
doc      └─┘
txt      └─┘
par      └─┘
st   ──────┘└─
827      simp only [mem_filter, not_and, iff_false, not_mem_empty],
id                  └────────┘  └─────┘  └───────┘  └───────────┘
src      └─────────┘└────────┘└┘└─────┘└┘└───────┘└┘└───────────┘
typ      └─────────┘└────────┘└┘└─────┘└┘└───────┘└┘└───────────┘
doc      └─────────┘          └┘       └┘         └┘             
txt      └─────────┘          └┘       └┘         └┘             
par      └─────────┘          └┘       └┘         └┘             
pid          └──┘└┘          └┘       └┘         └┘             
st   ────────────────────────────────────────────────────────────┘└─
828      rintros m ⟨e⟩, exact h m, }
id                             
src      └───────────┘  └────┘ 
typ      └───────────┘  └────┘
doc      └───────────┘  └────┘ 
txt      └───────────┘  └────┘ 
par      └───────────┘  └────┘ 
pid             └────┘        
st   ────────────────┘└─────────┘└───
829  end
st   ──┘
830  
831  /--
832    After filtering out everything that does not equal a given value, at most that value remains.
833  
834    This is equivalent to `filter_eq` with the equality the other way.
835  -/
836  lemma filter_eq' [decidable_eq β] (s : finset β) (b : β) :
id                     └──────────┘        └────┘        
src                    └──────────┘         └────┘
typ                    └──────────┘        └────┘        
doc                                         └────┘
837    s.filter (λ a, a = b) = ite (b ∈ s) {b} ∅ :=
id     └─────┘           └─┘        
src     └─────┘              └─┘           
typ    └─────┘           └─┘        
doc     └─────┘
838  trans (filter_congr (λ _ _, ⟨eq.symm, eq.symm⟩)) (filter_eq s b)
id   └───┘  └──────────┘        └─────┘  └─────┘     └───────┘  
src  └───┘  └──────────┘          └─────┘  └─────┘     └───────┘
typ  └───┘  └──────────┘        └─────┘  └─────┘     └───────┘  
doc                                                    └───────┘
839  
840  end filter
841  
842  /-! ### range -/
843  section range
844  variables {n m l : ℕ}
id                      
src                     
typ                     
845  
846  /-- `range n` is the set of natural numbers less than `n`. -/
847  def range (n : ℕ) : finset ℕ := ⟨_, nodup_range n⟩
id                      └────┘         └─────────┘ 
src                     └────┘         └─────────┘
typ                     └────┘         └─────────┘ 
doc                      └────┘
848  
849  @[simp] theorem range_val (n : ℕ) : (range n).1 = multiset.range n := rfl
id                                       └───┘     └────────────┘     └─┘
src                                      └───┘      └────────────┘      └─┘
typ                                      └───┘     └────────────┘     └─┘
doc    └──┘                               └───┘        └────────────┘
850  
851  @[simp] theorem mem_range : m ∈ range n ↔ m < n := mem_range
id                                 └───┘         └───────┘
src                                 └───┘            └───────┘
typ                                └───┘         └───────┘
doc    └──┘                          └───┘
852  
853  @[simp] theorem range_zero : range 0 = ∅ := rfl
id                                └───┘        └─┘
src                               └───┘        └─┘
typ                               └───┘        └─┘
doc    └──┘                       └───┘
854  
855  @[simp] theorem range_one : range 1 = {0} := rfl
id                               └───┘          └─┘
src                              └───┘          └─┘
typ                              └───┘          └─┘
doc    └──┘                      └───┘
856  
857  theorem range_succ : range (succ n) = insert n (range n) :=
id                        └───┘  └──┘    └────┘   └───┘ 
src                       └───┘  └──┘     └────┘    └───┘
typ                       └───┘  └──┘    └────┘   └───┘ 
doc                       └───┘                      └───┘
858  eq_of_veq $ (range_succ n).trans $ (ndinsert_of_not_mem not_mem_range_self).symm
id   └───────┘    └────────┘  └───┘     └─────────────────┘ └────────────────┘ └──┘
src  └───────┘    └────────┘   └───┘     └─────────────────┘ └────────────────┘ └──┘
typ  └───────┘    └────────┘  └───┘     └─────────────────┘ └────────────────┘ └──┘
859  
860  theorem range_add_one : range (n + 1) = insert n (range n) :=
id                           └───┘        └────┘   └───┘ 
src                          └───┘         └────┘    └───┘
typ                          └───┘        └────┘   └───┘ 
doc                          └───┘                     └───┘
861  range_succ
id   └────────┘
src  └────────┘
typ  └────────┘
862  
863  @[simp] theorem not_mem_range_self : n ∉ range n := not_mem_range_self
id                                          └───┘     └────────────────┘
src                                          └───┘      └────────────────┘
typ                                         └───┘     └────────────────┘
doc    └──┘                                   └───┘
864  
865  @[simp] theorem range_subset {n m} : range n ⊆ range m ↔ n ≤ m := range_subset
id                                        └───┘   └───┘         └──────────┘
src                                       └───┘    └───┘            └──────────┘
typ                                       └───┘   └───┘         └──────────┘
doc    └──┘                               └───┘     └───┘
866  
867  theorem range_mono : monotone range := λ _ _, range_subset.2
id                        └──────┘ └───┘         └──────────┘
src                       └──────┘ └───┘           └──────────┘
typ                       └──────┘ └───┘         └──────────┘
doc                       └──────┘ └───┘
868  
869  end range
870  
871  /- useful rules for calculations with quantifiers -/
872  theorem exists_mem_empty_iff (p : α → Prop) : (∃ x, x ∈ (∅ : finset α) ∧ p x) ↔ false :=
id                                                         └────┘        └───┘
src                                                           └────┘           └───┘
typ                                                        └────┘        └───┘
doc                                                               └────┘
873  by simp only [not_mem_empty, false_and, exists_false]
id                 └───────────┘  └───────┘  └──────────┘
src     └─────────┘└───────────┘└┘└───────┘└┘└──────────┘└─
typ     └─────────┘└───────────┘└┘└───────┘└┘└──────────┘└─
doc     └─────────┘             └┘         └┘            └─
txt     └─────────┘             └┘         └┘            └─
par     └─────────┘             └┘         └┘            └─
pid         └──┘└┘             └┘         └┘            
st     └───────────────────────────────────────────────────
874  
src  
typ  
doc  
txt  
par  
pid  
st   
875  theorem exists_mem_insert [d : decidable_eq α]
id                                  └──────────┘ 
src                                 └──────────┘
typ                                 └──────────┘ 
876      (a : α) (s : finset α) (p : α → Prop) :
id                   └────┘        
src                   └────┘
typ                  └────┘        
doc                   └────┘
877    (∃ x, x ∈ insert a s ∧ p x) ↔ p a ∨ (∃ x, x ∈ s ∧ p x) :=
id          └────┘                   
src           └────┘                          
typ         └────┘                   
878  by simp only [mem_insert, or_and_distrib_right, exists_or_distrib, exists_eq_left]
id                 └────────┘  └──────────────────┘  └───────────────┘  └────────────┘
src     └─────────┘└────────┘└┘└──────────────────┘└┘└───────────────┘└┘└────────────┘└─
typ     └─────────┘└────────┘└┘└──────────────────┘└┘└───────────────┘└┘└────────────┘└─
doc     └─────────┘          └┘                    └┘                 └┘              └─
txt     └─────────┘          └┘                    └┘                 └┘              └─
par     └─────────┘          └┘                    └┘                 └┘              └─
pid         └──┘└┘          └┘                    └┘                 └┘              
st     └────────────────────────────────────────────────────────────────────────────────
879  
src  
typ  
doc  
txt  
par  
pid  
st   
880  theorem forall_mem_empty_iff (p : α → Prop) : (∀ x, x ∈ (∅ : finset α) → p x) ↔ true :=
id                                                           └────┘         └──┘
src                                                             └────┘            └──┘
typ                                                          └────┘         └──┘
doc                                                               └────┘
881  iff_true_intro $ λ _, false.elim
id   └────────────┘       └────────┘
src  └────────────┘        └────────┘
typ  └────────────┘       └────────┘
882  
883  theorem forall_mem_insert [d : decidable_eq α]
id                                  └──────────┘ 
src                                 └──────────┘
typ                                 └──────────┘ 
884      (a : α) (s : finset α) (p : α → Prop) :
id                   └────┘        
src                   └────┘
typ                  └────┘        
doc                   └────┘
885    (∀ x, x ∈ insert a s → p x) ↔ p a ∧ (∀ x, x ∈ s → p x) :=
id            └────┘                       
src             └────┘                          
typ           └────┘                       
886  by simp only [mem_insert, or_imp_distrib, forall_and_distrib, forall_eq]
id                 └────────┘  └────────────┘  └────────────────┘  └───────┘
src     └─────────┘└────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└─
typ     └─────────┘└────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└─
doc     └─────────┘          └┘              └┘                  └┘         └─
txt     └─────────┘          └┘              └┘                  └┘         └─
par     └─────────┘          └┘              └┘                  └┘         └─
pid         └──┘└┘          └┘              └┘                  └┘         
st     └──────────────────────────────────────────────────────────────────────
887  
src  
typ  
doc  
txt  
par  
pid  
st   
888  end finset
889  
890  namespace option
891  
892  /-- Construct an empty or singleton finset from an `option` -/
893  def to_finset (o : option α) : finset α :=
id                      └────┘     └────┘ 
src                     └────┘      └────┘
typ                     └────┘     └────┘ 
doc                                 └────┘
894  match o with
id         
typ        
895  | none   := ∅
id     └──┘      
src    └──┘      
typ    └──┘      
896  | some a := finset.singleton a
id     └──┘     └──────────────┘
src    └──┘      └──────────────┘
typ    └──┘     └──────────────┘
doc              └──────────────┘
897  end
898  
899  @[simp] theorem to_finset_none : none.to_finset = (∅ : finset α) := rfl
id                                    └──┘└────────┘      └────┘      └─┘
src                                   └──┘└────────┘      └────┘       └─┘
typ                                   └──┘└────────┘      └────┘      └─┘
doc    └──┘                               └────────┘        └────┘
900  
901  @[simp] theorem to_finset_some {a : α} : (some a).to_finset = finset.singleton a := rfl
id                                            └──┘  └───────┘   └──────────────┘     └─┘
src                                            └──┘   └───────┘   └──────────────┘      └─┘
typ                                           └──┘  └───────┘   └──────────────┘     └─┘
doc    └──┘                                           └───────┘    └──────────────┘
902  
903  @[simp] theorem mem_to_finset {a : α} {o : option α} : a ∈ o.to_finset ↔ a ∈ o :=
id                                             └────┘       └────────┘    
src                                             └────┘          └────────┘    
typ                                            └────┘       └────────┘    
doc    └──┘                                                      └────────┘
904  by cases o; simp only [to_finset, finset.mem_singleton, option.mem_def, eq_comm]; refl
id                         └───────┘  └──────────────────┘  └────────────┘  └─────┘
src     └────┘   └─────────┘└───────┘└┘└──────────────────┘└┘└────────────┘└┘└─────┘  └────
typ     └────┘  └─────────┘└───────┘└┘└──────────────────┘└┘└────────────┘└┘└─────┘  └────
doc     └────┘   └─────────┘└───────┘└┘                    └┘              └┘         └────
txt     └────┘   └─────────┘         └┘                    └┘              └┘         └────
par     └────┘   └─────────┘         └┘                    └┘              └┘         └────
pid                 └──┘└┘         └┘                    └┘              └┘             
st     └────────────────────────────────────────────────────────────────────────────────────
905  
src  
typ  
doc  
txt  
par  
pid  
st   
906  end option
907  
908  /-! ### erase_dup on list and multiset -/
909  
910  namespace multiset
911  variable [decidable_eq α]
id             └──────────┘
src            └──────────┘
typ            └──────────┘
912  
913  /-- `to_finset s` removes duplicates from the multiset `s` to produce a finset. -/
914  def to_finset (s : multiset α) : finset α := ⟨_, nodup_erase_dup s⟩
id                      └──────┘     └────┘         └─────────────┘ 
src                     └──────┘      └────┘          └─────────────┘
typ                     └──────┘     └────┘         └─────────────┘ 
doc                     └──────┘      └────┘
915  
916  @[simp] theorem to_finset_val (s : multiset α) : s.to_finset.1 = s.erase_dup := rfl
id                                      └──────┘     └────────┘   └────────┘    └─┘
src                                     └──────┘       └────────┘    └────────┘    └─┘
typ                                     └──────┘     └────────┘   └────────┘    └─┘
doc    └──┘                             └──────┘       └────────┘      └────────┘
917  
918  theorem to_finset_eq {s : multiset α} (n : nodup s) : finset.mk s n = s.to_finset :=
id                             └──────┘        └───┘     └───────┘    └────────┘
src                            └──────┘         └───┘      └───────┘       └────────┘
typ                            └──────┘        └───┘     └───────┘    └────────┘
doc                            └──────┘         └───┘                       └────────┘
919  finset.val_inj.1 (erase_dup_eq_self.2 n).symm
id   └────────────┘   └───────────────┘   └──┘
src  └────────────┘   └───────────────┘    └──┘
typ  └────────────┘   └───────────────┘   └──┘
920  
921  @[simp] theorem mem_to_finset {a : α} {s : multiset α} : a ∈ s.to_finset ↔ a ∈ s :=
id                                             └──────┘       └────────┘    
src                                             └──────┘          └────────┘    
typ                                            └──────┘       └────────┘    
doc    └──┘                                     └──────┘           └────────┘
922  mem_erase_dup
id   └───────────┘
src  └───────────┘
typ  └───────────┘
923  
924  @[simp] lemma to_finset_zero :
doc    └──┘
925    to_finset (0 : multiset α) = ∅ :=
id     └───────┘      └──────┘    
src    └───────┘      └──────┘     
typ    └───────┘      └──────┘    
doc    └───────┘      └──────┘
926  rfl
id   └─┘
src  └─┘
typ  └─┘
927  
928  @[simp] lemma to_finset_cons (a : α) (s : multiset α) :
id                                            └──────┘ 
src                                            └──────┘
typ                                           └──────┘ 
doc    └──┘                                    └──────┘
929    to_finset (a :: s) = insert a (to_finset s) :=
id     └───────┘   └┘    └────┘   └───────┘ 
src    └───────┘    └┘     └────┘    └───────┘
typ    └───────┘   └┘    └────┘   └───────┘ 
doc    └───────┘    └┘                └───────┘
930  finset.eq_of_veq erase_dup_cons
id   └──────────────┘ └────────────┘
src  └──────────────┘ └────────────┘
typ  └──────────────┘ └────────────┘
931  
932  @[simp] lemma to_finset_add (s t : multiset α) :
id                                      └──────┘ 
src                                     └──────┘
typ                                     └──────┘ 
doc    └──┘                             └──────┘
933    to_finset (s + t) = to_finset s ∪ to_finset t :=
id     └───────┘       └───────┘   └───────┘ 
src    └───────┘         └───────┘    └───────┘
typ    └───────┘       └───────┘   └───────┘ 
doc    └───────┘           └───────┘     └───────┘
934  finset.ext' $ by simp
id   └─────────┘
src  └─────────┘      └────
typ  └─────────┘      └────
doc                   └────
txt                   └────
par                   └────
pid                       
st                   └─────
935  
src  
typ  
doc  
txt  
par  
pid  
st   
936  @[simp] lemma to_finset_smul (s : multiset α) :
id                                     └──────┘ 
src                                    └──────┘
typ                                    └──────┘ 
doc    └──┘                            └──────┘
937    ∀(n : ℕ) (hn : n ≠ 0), (add_monoid.smul n s).to_finset = s.to_finset
id                         └─────────────┘   └───────┘   └────────┘
src                          └─────────────┘     └───────┘    └────────┘
typ                        └─────────────┘   └───────┘   └────────┘
doc                                                └───────┘     └────────┘
938  | 0     h := by contradiction
src                  └────────────┘
typ                  └────────────┘
doc                  └────────────┘
txt                  └────────────┘
par                  └────────────┘
pid                               
st                  └─────────────┘
939  | (n+1) h :=
id       
src      
typ      
940    begin
st     └─────
941      by_cases n = 0,
id                 
src      └───────┘ └┘
typ      └───────┘└┘
doc      └───────┘  └┘
txt      └───────┘  └┘
par      └───────┘  └┘
pid                
st   ─────────────────┘└─
942      { rw [h, zero_add, add_monoid.one_smul] },
id               └──────┘  └─────────────────┘
src        └──┘ └┘└──────┘└┘└─────────────────┘└┘
typ        └──┘└┘└──────┘└┘└─────────────────┘└┘
doc        └──┘ └┘        └┘                   └┘
txt        └──┘ └┘        └┘                   └┘
par        └──┘ └┘        └┘                   └┘
pid          └┘ └┘        └┘                   
st   ─────┘└───┘└────────┘└───────────────────┘└┘
943      { rw [add_monoid.add_smul, to_finset_add, add_monoid.one_smul, to_finset_smul n h,
id             └─────────────────┘  └───────────┘  └─────────────────┘  └────────────┘  
src        └──┘└─────────────────┘└┘└───────────┘└┘└─────────────────┘└┘                └─
typ        └──┘└─────────────────┘└┘└───────────┘└┘└─────────────────┘└┘└────────────┘└─
doc        └──┘                   └┘             └┘                   └┘                └─
txt        └──┘                   └┘             └┘                   └┘                └─
par        └──┘                   └┘             └┘                   └┘                └─
pid          └┘                   └┘             └┘                   └┘                └─
st   ────────────────────────────┘└─────────────┘└───────────────────┘└──────────────────┘└─
944          finset.union_idempotent] }
id           └─────────────────────┘
src  ───────┘└─────────────────────┘└┘
typ  ───────┘└─────────────────────┘└┘
doc  ───────┘                       └┘
txt  ───────┘                       └┘
par  ───────┘                       └┘
pid  ───────┘                       
st   ──────────────────────────────┘└─
945    end
st   ────┘
946  
947  @[simp] lemma to_finset_inter (s t : multiset α) :
id                                        └──────┘ 
src                                       └──────┘
typ                                       └──────┘ 
doc    └──┘                               └──────┘
948    to_finset (s ∩ t) = to_finset s ∩ to_finset t :=
id     └───────┘       └───────┘   └───────┘ 
src    └───────┘         └───────┘    └───────┘
typ    └───────┘       └───────┘   └───────┘ 
doc    └───────┘           └───────┘     └───────┘
949  finset.ext' $ by simp
id   └─────────┘
src  └─────────┘      └────
typ  └─────────┘      └────
doc                   └────
txt                   └────
par                   └────
pid                       
st                   └─────
950  
src  
typ  
doc  
txt  
par  
pid  
st   
951  theorem to_finset_eq_empty {m : multiset α} : m.to_finset = ∅ ↔ m = 0 :=
id                                   └──────┘     └────────┘     
src                                  └──────┘       └────────┘      
typ                                  └──────┘     └────────┘     
doc                                  └──────┘       └────────┘
952  finset.val_inj.symm.trans multiset.erase_dup_eq_zero
id   └────────────┘└───┘└────┘ └────────────────────────┘
src  └────────────┘└───┘└────┘ └────────────────────────┘
typ  └────────────┘└───┘└────┘ └────────────────────────┘
953  
954  end multiset
955  
956  namespace list
957  variable [decidable_eq α]
id             └──────────┘
src            └──────────┘
typ            └──────────┘
958  
959  /-- `to_finset l` removes duplicates from the list `l` to produce a finset. -/
960  def to_finset (l : list α) : finset α := multiset.to_finset l
id                      └──┘     └────┘     └────────────────┘ 
src                     └──┘      └────┘      └────────────────┘
typ                     └──┘     └────┘     └────────────────┘ 
doc                               └────┘      └────────────────┘
961  
962  @[simp] theorem to_finset_val (l : list α) : l.to_finset.1 = (l.erase_dup : multiset α) := rfl
id                                      └──┘     └────────┘    └────────┘   └──────┘      └─┘
src                                     └──┘       └────────┘     └────────┘   └──────┘       └─┘
typ                                     └──┘     └────────┘    └────────┘   └──────┘      └─┘
doc    └──┘                                        └────────┘       └────────┘   └──────┘
963  
964  theorem to_finset_eq {l : list α} (n : nodup l) : @finset.mk α l n = l.to_finset :=
id                             └──┘        └───┘      └───────┘     └────────┘
src                            └──┘         └───┘       └───────┘         └────────┘
typ                            └──┘        └───┘      └───────┘     └────────┘
doc                                         └───┘                          └────────┘
965  multiset.to_finset_eq n
id   └───────────────────┘ 
src  └───────────────────┘
typ  └───────────────────┘ 
966  
967  @[simp] theorem mem_to_finset {a : α} {l : list α} : a ∈ l.to_finset ↔ a ∈ l :=
id                                             └──┘       └────────┘    
src                                             └──┘          └────────┘    
typ                                            └──┘       └────────┘    
doc    └──┘                                                    └────────┘
968  mem_erase_dup
id   └───────────┘
src  └───────────┘
typ  └───────────┘
969  
970  @[simp] theorem to_finset_nil : to_finset (@nil α) = ∅ :=
id                                   └───────┘   └─┘    
src                                  └───────┘   └─┘     
typ                                  └───────┘   └─┘    
doc    └──┘                          └───────┘
971  rfl
id   └─┘
src  └─┘
typ  └─┘
972  
973  @[simp] theorem to_finset_cons {a : α} {l : list α} : to_finset (a :: l) = insert a (to_finset l) :=
id                                              └──┘     └───────┘   └┘    └────┘   └───────┘ 
src                                              └──┘      └───────┘    └┘     └────┘    └───────┘
typ                                             └──┘     └───────┘   └┘    └────┘   └───────┘ 
doc    └──┘                                                └───────┘                      └───────┘
974  finset.eq_of_veq $ by by_cases h : a ∈ l; simp [finset.insert_val', multiset.erase_dup_cons, h]
id   └──────────────┘                             └────────────────┘  └─────────────────────┘  
src  └──────────────┘      └───────┘ └─┘    └────┘└────────────────┘└┘└─────────────────────┘└┘ └─
typ  └──────────────┘      └───────┘ └─┘  └────┘└────────────────┘└┘└─────────────────────┘└┘└─
doc                        └───────┘ └─┘     └────┘                  └┘                       └┘ └─
txt                        └───────┘ └─┘     └────┘                  └┘                       └┘ └─
par                        └───────┘ └─┘     └────┘                  └┘                       └┘ └─
pid                                 └─┘                           └┘                       └┘ 
st                        └──────────────────────────────────────────────────────────────────────────
975  
src  
typ  
doc  
txt  
par  
pid  
st   
976  end list
977  
978  namespace finset
979  
980  /-! ### map -/
981  section map
982  open function
983  
984  def map (f : α ↪ β) (s : finset α) : finset β :=
id                         └────┘     └────┘ 
src                          └────┘      └────┘
typ                        └────┘     └────┘ 
doc                           └────┘      └────┘
985  ⟨s.1.map f, nodup_map f.2 s.2⟩
id     └─┘    └───────┘   
src     └─┘     └───────┘     
typ    └─┘    └───────┘   
doc      └─┘
986  
987  @[simp] theorem map_val (f : α ↪ β) (s : finset α) : (map f s).1 = s.1.map f := rfl
id                                         └────┘      └─┘       └─┘      └─┘
src                                          └────┘       └─┘          └─┘       └─┘
typ                                        └────┘      └─┘       └─┘      └─┘
doc    └──┘                                   └────┘                       └─┘
988  
989  @[simp] theorem map_empty (f : α ↪ β) : (∅ : finset α).map f = ∅ := rfl
id                                            └────┘  └─┘        └─┘
src                                             └────┘   └─┘         └─┘
typ                                           └────┘  └─┘        └─┘
doc    └──┘                                       └────┘
990  
991  variables {f : α ↪ β} {s : finset α}
id                             └────┘
src                            └────┘
typ                            └────┘
doc                             └────┘
992  
993  @[simp] theorem mem_map {b : β} : b ∈ s.map f ↔ ∃ a ∈ s, f a = b :=
id                                      └──┘           
src                                        └──┘               
typ                                     └──┘           
doc    └──┘
994  mem_map.trans $ by simp only [exists_prop]; refl
id   └─────┘└────┘                 └─────────┘
src  └─────┘└────┘      └─────────┘└─────────┘  └────
typ  └─────┘└────┘      └─────────┘└─────────┘  └────
doc                     └─────────┘             └────
txt                     └─────────┘             └────
par                     └─────────┘             └────
pid                         └──┘└┘                 
st                     └──────────────────────────────
995  
src  
typ  
doc  
txt  
par  
pid  
st   
996  theorem mem_map' (f : α ↪ β) {a} {s : finset α} : f a ∈ s.map f ↔ a ∈ s :=
id                                      └────┘        └──┘     
src                                       └────┘            └──┘      
typ                                     └────┘        └──┘     
doc                                        └────┘
997  mem_map_of_inj f.2
id   └────────────┘ 
src  └────────────┘  
typ  └────────────┘ 
998  
999  @[simp] theorem mem_map_of_mem (f : α ↪ β) {a} {s : finset α} : a ∈ s → f a ∈ s.map f :=
id                                                    └────┘             └──┘ 
src                                                     └────┘                   └──┘
typ                                                   └────┘             └──┘ 
doc    └──┘                                              └────┘
1000  (mem_map' _).2
id    └──────┘   
src   └──────┘   
typ   └──────┘   
1001  
1002  theorem map_to_finset [decidable_eq α] [decidable_eq β] {s : multiset α} :
id                          └──────────┘    └──────────┘        └──────┘ 
src                         └──────────┘     └──────────┘         └──────┘
typ                         └──────────┘    └──────────┘        └──────┘ 
doc                                                               └──────┘
1003    s.to_finset.map f = (s.map f).to_finset :=
id     └────────┘└──┘    └──┘  └───────┘
src     └────────┘└──┘      └──┘   └───────┘
typ    └────────┘└──┘    └──┘  └───────┘
doc     └────────┘           └──┘   └───────┘
1004  ext.2 $ λ _, by simp only [mem_map, multiset.mem_map, exists_prop, multiset.mem_to_finset]
id   └─┘                      └─────┘  └──────────────┘  └─────────┘  └────────────────────┘
src  └─┘            └─────────┘└─────┘└┘└──────────────┘└┘└─────────┘└┘└────────────────────┘└─
typ  └─┘           └─────────┘└─────┘└┘└──────────────┘└┘└─────────┘└┘└────────────────────┘└─
doc                  └─────────┘       └┘                └┘           └┘                      └─
txt                  └─────────┘       └┘                └┘           └┘                      └─
par                  └─────────┘       └┘                └┘           └┘                      └─
pid                      └──┘└┘       └┘                └┘           └┘                      
st                  └───────────────────────────────────────────────────────────────────────────
1005  
src  
typ  
doc  
txt  
par  
pid  
st   
1006  theorem map_refl : s.map (embedding.refl _) = s :=
id                      └──┘  └────────────┘     
src                      └──┘  └────────────┘    
typ                     └──┘  └────────────┘     
1007  ext.2 $ λ _, by simpa only [mem_map, exists_prop] using exists_eq_right
id   └─┘                       └─────┘  └─────────┘        └─────────────┘
src  └─┘            └──────────┘└─────┘└┘└─────────┘└──────┘└─────────────┘
typ  └─┘           └──────────┘└─────┘└┘└─────────┘└──────┘└─────────────┘
doc                  └──────────┘       └┘           └──────┘               
txt                  └──────────┘       └┘           └──────┘               
par                  └──────────┘       └┘           └──────┘               
pid                       └──┘└┘       └┘           └────┘               
st                  └────────────────────────────────────────────────────────
1008  
src  
typ  
doc  
txt  
par  
pid  
st   
1009  theorem map_map {g : β ↪ γ} : (s.map f).map g = s.map (f.trans g) :=
id                               └──┘  └─┘    └──┘  └────┘ 
src                                 └──┘   └─┘      └──┘   └────┘
typ                              └──┘  └─┘    └──┘  └────┘ 
1010  eq_of_veq $ by simp only [map_val, multiset.map_map]; refl
id   └───────┘                 └─────┘  └──────────────┘
src  └───────┘      └─────────┘└─────┘└┘└──────────────┘  └────
typ  └───────┘      └─────────┘└─────┘└┘└──────────────┘  └────
doc                 └─────────┘       └┘                  └────
txt                 └─────────┘       └┘                  └────
par                 └─────────┘       └┘                  └────
pid                     └──┘└┘       └┘                      
st                 └────────────────────────────────────────────
1011  
src  
typ  
doc  
txt  
par  
pid  
st   
1012  theorem map_subset_map {s₁ s₂ : finset α} : s₁.map f ⊆ s₂.map f ↔ s₁ ⊆ s₂ :=
id                                   └────┘     └┘└──┘   └┘└──┘   └┘  └┘
src                                  └────┘        └──┘      └──┘       
typ                                  └────┘     └┘└──┘   └┘└──┘   └┘  └┘
doc                                  └────┘
1013  ⟨λ h x xs, (mem_map' _).1 $ h $ (mem_map' f).2 xs,
id        └┘   └──────┘           └──────┘    └┘
src              └──────┘            └──────┘   
typ       └┘   └──────┘           └──────┘    └┘
1014   λ h, by simp [subset_def, map_subset_map h]⟩
id                 └────────┘  └────────────┘ 
src           └────┘└────────┘└┘└────────────┘ 
typ          └────┘└────────┘└┘└────────────┘
doc           └────┘          └┘               
txt           └────┘          └┘               
par           └────┘          └┘               
pid                         └┘               
st           └──────────────────────────────────┘
1015  
1016  theorem map_inj {s₁ s₂ : finset α} : s₁.map f = s₂.map f ↔ s₁ = s₂ :=
id                            └────┘     └┘└──┘   └┘└──┘   └┘  └┘
src                           └────┘        └──┘      └──┘       
typ                           └────┘     └┘└──┘   └┘└──┘   └┘  └┘
doc                           └────┘
1017  by simp only [subset.antisymm_iff, map_subset_map]
id                 └─────────────────┘  └────────────┘
src     └─────────┘└─────────────────┘└┘└────────────┘└─
typ     └─────────┘└─────────────────┘└┘└────────────┘└─
doc     └─────────┘                   └┘              └─
txt     └─────────┘                   └┘              └─
par     └─────────┘                   └┘              └─
pid         └──┘└┘                   └┘              
st     └────────────────────────────────────────────────
1018  
src  
typ  
doc  
txt  
par  
pid  
st   
1019  def map_embedding (f : α ↪ β) : finset α ↪ finset β := ⟨map f, λ s₁ s₂, map_inj.1⟩
id                                └────┘   └────┘      └─┘     └┘ └┘  └─────┘
src                                 └────┘    └────┘       └─┘             └─────┘
typ                               └────┘   └────┘      └─┘     └┘ └┘  └─────┘
doc                                  └────┘     └────┘
1020  
1021  @[simp] theorem map_embedding_apply : map_embedding f s = map f s := rfl
id                                         └───────────┘    └─┘      └─┘
src                                        └───────────┘      └─┘        └─┘
typ                                        └───────────┘    └─┘      └─┘
doc    └──┘
1022  
1023  theorem map_filter {p : β → Prop} [decidable_pred p] :
id                                     └────────────┘ 
src                                     └────────────┘
typ                                    └────────────┘ 
1024    (s.map f).filter p = (s.filter (p ∘ f)).map f :=
id      └──┘  └────┘     └─────┘      └─┘  
src      └──┘   └────┘       └─────┘        └─┘
typ     └──┘  └────┘     └─────┘      └─┘  
doc             └────┘        └─────┘
1025  ext.2 $ λ b, by simp only [mem_filter, mem_map, exists_prop, and_assoc]; exact
id   └─┘                      └────────┘  └─────┘  └─────────┘  └───────┘
src  └─┘            └─────────┘└────────┘└┘└─────┘└┘└─────────┘└┘└───────┘  └────┘
typ  └─┘           └─────────┘└────────┘└┘└─────┘└┘└─────────┘└┘└───────┘  └────┘
doc                  └─────────┘          └┘       └┘           └┘           └────┘
txt                  └─────────┘          └┘       └┘           └┘           └────┘
par                  └─────────┘          └┘       └┘           └┘           └────┘
pid                      └──┘└┘          └┘       └┘           └┘                
st                  └───────────────────────────────────────────────────────────────
1026  ⟨by rintro ⟨⟨x, h1, rfl⟩, h2⟩; exact ⟨x, h1, h2, rfl⟩,
id                                           └┘  └┘  └─┘
src     └───────────────────────┘└──────┘  └┘  └┘  └┘└─┘└─┘
typ     └───────────────────────┘└──────┘ └┘└┘└┘└┘└┘└─┘└─┘
doc     └───────────────────────┘└──────┘  └┘  └┘  └┘   └─┘
txt     └───────────────────────┘└──────┘  └┘  └┘  └┘   └─┘
par     └───────────────────────┘└──────┘  └┘  └┘  └┘   └─┘
pid     └────────────────────────────────┘  └┘  └┘  └┘   └─┘
st   ──┘└────────────────────────────────────────────────┘└─
1027  by rintro ⟨x, h1, h2, rfl⟩; exact ⟨⟨x, h1, rfl⟩, h2⟩⟩
id                                         └┘  └─┘   └┘
src    └─────────────────────┘└──────┘   └┘  └┘└─┘└─┘  └──
typ    └─────────────────────┘└──────┘  └┘└┘└┘└─┘└─┘└┘└──
doc    └─────────────────────┘└──────┘   └┘  └┘   └─┘  └──
txt    └─────────────────────┘└──────┘   └┘  └┘   └─┘  └──
par    └─────────────────────┘└──────┘   └┘  └┘   └─┘  └──
pid    └──────────────────────────────┘   └┘  └┘   └─┘  └┘
st   ─┘└────────────────────────────────────────────────┘└─
1028  
src  
typ  
doc  
txt  
par  
pid  
st   
1029  theorem map_union [decidable_eq α] [decidable_eq β]
id                      └──────────┘    └──────────┘ 
src                     └──────────┘     └──────────┘
typ                     └──────────┘    └──────────┘ 
1030    {f : α ↪ β} (s₁ s₂ : finset α) : (s₁ ∪ s₂).map f = s₁.map f ∪ s₂.map f :=
id                       └────┘      └┘  └┘ └─┘    └┘└──┘   └┘└──┘ 
src                        └────┘              └─┘       └──┘      └──┘
typ                      └────┘      └┘  └┘ └─┘    └┘└──┘   └┘└──┘ 
doc                         └────┘
1031  ext.2 $ λ _, by simp only [mem_map, mem_union, exists_prop, or_and_distrib_right, exists_or_distrib]
id   └─┘                      └─────┘  └───────┘  └─────────┘  └──────────────────┘  └───────────────┘
src  └─┘            └─────────┘└─────┘└┘└───────┘└┘└─────────┘└┘└──────────────────┘└┘└───────────────┘└─
typ  └─┘           └─────────┘└─────┘└┘└───────┘└┘└─────────┘└┘└──────────────────┘└┘└───────────────┘└─
doc                  └─────────┘       └┘         └┘           └┘                    └┘                 └─
txt                  └─────────┘       └┘         └┘           └┘                    └┘                 └─
par                  └─────────┘       └┘         └┘           └┘                    └┘                 └─
pid                      └──┘└┘       └┘         └┘           └┘                    └┘                 
st                  └─────────────────────────────────────────────────────────────────────────────────────
1032  
src  
typ  
doc  
txt  
par  
pid  
st   
1033  theorem map_inter [decidable_eq α] [decidable_eq β]
id                      └──────────┘    └──────────┘ 
src                     └──────────┘     └──────────┘
typ                     └──────────┘    └──────────┘ 
1034    {f : α ↪ β} (s₁ s₂ : finset α) : (s₁ ∩ s₂).map f = s₁.map f ∩ s₂.map f :=
id                       └────┘      └┘  └┘ └─┘    └┘└──┘   └┘└──┘ 
src                        └────┘              └─┘       └──┘      └──┘
typ                      └────┘      └┘  └┘ └─┘    └┘└──┘   └┘└──┘ 
doc                         └────┘
1035  ext.2 $ λ b, by simp only [mem_map, mem_inter, exists_prop]; exact
id   └─┘                      └─────┘  └───────┘  └─────────┘
src  └─┘            └─────────┘└─────┘└┘└───────┘└┘└─────────┘  └────┘
typ  └─┘           └─────────┘└─────┘└┘└───────┘└┘└─────────┘  └────┘
doc                  └─────────┘       └┘         └┘             └────┘
txt                  └─────────┘       └┘         └┘             └────┘
par                  └─────────┘       └┘         └┘             └────┘
pid                      └──┘└┘       └┘         └┘                  
st                  └───────────────────────────────────────────────────
1036  ⟨by rintro ⟨a, ⟨m₁, m₂⟩, rfl⟩; exact ⟨⟨a, m₁, rfl⟩, ⟨a, m₂, rfl⟩⟩,
id                                             └┘           └┘  └─┘
src     └───────────────────────┘└──────┘   └┘  └┘   └─┘  └┘  └┘└─┘└──┘
typ     └───────────────────────┘└──────┘   └┘└┘└┘   └─┘ └┘└┘└┘└─┘└──┘
doc     └───────────────────────┘└──────┘   └┘  └┘   └─┘  └┘  └┘   └──┘
txt     └───────────────────────┘└──────┘   └┘  └┘   └─┘  └┘  └┘   └──┘
par     └───────────────────────┘└──────┘   └┘  └┘   └─┘  └┘  └┘   └──┘
pid     └────────────────────────────────┘   └┘  └┘   └─┘  └┘  └┘   └──┘
st   ──┘└────────────────────────────────────────────────────────────┘└─
1037  by rintro ⟨⟨a, m₁, e⟩, ⟨a', m₂, rfl⟩⟩; cases f.2 e; exact ⟨_, ⟨m₁, m₂⟩, rfl⟩⟩
id                                                                └┘  └┘   └─┘
src    └────────────────────────────────┘└┘└────┘ └─┘ └──────┘ └─┘   └┘  └─┘└─┘└──
typ    └────────────────────────────────┘└┘└────┘└─┘└──────┘ └─┘ └┘└┘└┘└─┘└─┘└──
doc    └────────────────────────────────┘└┘└────┘ └─┘ └──────┘ └─┘   └┘  └─┘   └──
txt    └────────────────────────────────┘└┘└────┘ └─┘ └──────┘ └─┘   └┘  └─┘   └──
par    └────────────────────────────────┘└┘└────┘ └─┘ └──────┘ └─┘   └┘  └─┘   └──
pid    └─────────────────────────────────────────┘ └─┘ └──────┘ └─┘   └┘  └─┘   └┘
st   ─┘└────────────────────────────────────────────────────────────────────────┘└─
1038  
src  
typ  
doc  
txt  
par  
pid  
st   
1039  @[simp] theorem map_singleton (f : α ↪ β) (a : α) : (singleton a).map f = singleton (f a) :=
id                                                    └───────┘  └─┘    └───────┘   
src                                                      └───────┘   └─┘     └───────┘
typ                                                   └───────┘  └─┘    └───────┘   
doc    └──┘                                               └───────┘            └───────┘
1040  ext.2 $ λ _, by simp only [mem_map, mem_singleton, exists_prop, exists_eq_left]; exact eq_comm
id   └─┘                      └─────┘  └───────────┘  └─────────┘  └────────────┘         └─────┘
src  └─┘            └─────────┘└─────┘└┘└───────────┘└┘└─────────┘└┘└────────────┘  └────┘└─────┘
typ  └─┘           └─────────┘└─────┘└┘└───────────┘└┘└─────────┘└┘└────────────┘  └────┘└─────┘
doc                  └─────────┘       └┘             └┘           └┘                └────┘       
txt                  └─────────┘       └┘             └┘           └┘                └────┘       
par                  └─────────┘       └┘             └┘           └┘                └────┘       
pid                      └──┘└┘       └┘             └┘           └┘                            
st                  └───────────────────────────────────────────────────────────────────────────────
1041  
src  
typ  
doc  
txt  
par  
pid  
st   
1042  @[simp] theorem map_insert [decidable_eq α] [decidable_eq β]
id                               └──────────┘    └──────────┘ 
src                              └──────────┘     └──────────┘
typ                              └──────────┘    └──────────┘ 
doc    └──┘
1043    (f : α ↪ β) (a : α) (s : finset α) :
id                          └────┘ 
src                            └────┘
typ                         └────┘ 
doc                             └────┘
1044    (insert a s).map f = insert (f a) (s.map f) :=
id      └────┘   └─┘    └────┘      └──┘ 
src     └────┘     └─┘     └────┘         └──┘
typ     └────┘   └─┘    └────┘      └──┘ 
1045  by simp only [insert_eq, insert_empty_eq_singleton, map_union, map_singleton]
id                 └───────┘  └───────────────────────┘  └───────┘  └───────────┘
src     └─────────┘└───────┘└┘└───────────────────────┘└┘└───────┘└┘└───────────┘└─
typ     └─────────┘└───────┘└┘└───────────────────────┘└┘└───────┘└┘└───────────┘└─
doc     └─────────┘         └┘                         └┘         └┘             └─
txt     └─────────┘         └┘                         └┘         └┘             └─
par     └─────────┘         └┘                         └┘         └┘             └─
pid         └──┘└┘         └┘                         └┘         └┘             
st     └───────────────────────────────────────────────────────────────────────────
1046  
src  
typ  
doc  
txt  
par  
pid  
st   
1047  @[simp] theorem map_eq_empty : s.map f = ∅ ↔ s = ∅ :=
id                                  └──┘       
src                                  └──┘         
typ                                 └──┘       
doc    └──┘
1048  ⟨λ h, eq_empty_of_forall_not_mem $
id        └────────────────────────┘
src        └────────────────────────┘
typ       └────────────────────────┘
1049   λ a m, ne_empty_of_mem (mem_map_of_mem _ m) h, λ e, e.symm ▸ rfl⟩
id         └─────────────┘  └────────────┘           └───┘  └─┘
src          └─────────────┘  └────────────┘               └───┘  └─┘
typ        └─────────────┘  └────────────┘           └───┘  └─┘
1050  
1051  lemma attach_map_val {s : finset α} : s.attach.map (embedding.subtype _) = s :=
id                             └────┘     └─────┘└──┘  └───────────────┘     
src                            └────┘       └─────┘└──┘  └───────────────┘    
typ                            └────┘     └─────┘└──┘  └───────────────┘     
doc                            └────┘       └─────┘
1052  eq_of_veq $ by rw [map_val, attach_val]; exact attach_map_val _
id   └───────┘          └─────┘  └────────┘         └────────────┘
src  └───────┘      └──┘└─────┘└┘└────────┘  └────┘└────────────┘└──
typ  └───────┘      └──┘└─────┘└┘└────────┘  └────┘└────────────┘└──
doc                 └──┘       └┘            └────┘              └──
txt                 └──┘       └┘            └────┘              └──
par                 └──┘       └┘            └────┘              └──
pid                   └┘       └┘                               └┘
st                 └──────────┘└──────────┘└────────────────────────
1053  
src  
typ  
doc  
txt  
par  
pid  
st   
1054  end map
1055  
1056  lemma range_add_one' (n : ℕ) :
id                             
src                            
typ                            
1057    range (n + 1) = insert 0 ((range n).map ⟨λi, i + 1, assume i j, nat.succ_inj⟩) :=
id     └───┘        └────┘     └───┘  └─┘                     └──────────┘
src    └───┘         └────┘     └───┘   └─┘                         └──────────┘
typ    └───┘        └────┘     └───┘  └─┘                     └──────────┘
doc    └───┘                      └───┘
1058  by ext (⟨⟩ | ⟨n⟩); simp [nat.succ_eq_add_one, nat.zero_lt_succ n]
id                            └─────────────────┘  └──────────────┘ 
src     └────────────┘  └────┘└─────────────────┘└┘└──────────────┘ └─
typ     └────────────┘  └────┘└─────────────────┘└┘└──────────────┘└─
doc     └────────────┘  └────┘                   └┘                 └─
txt     └────────────┘  └────┘                   └┘                 └─
par     └────────────┘  └────┘                   └┘                 └─
pid        └─────────┘                         └┘                 
st     └───────────────────────────────────────────────────────────────
1059  
src  
typ  
doc  
txt  
par  
pid  
st   
1060  /-! ### image -/
1061  section image
1062  variables [decidable_eq β]
id              └──────────┘
src             └──────────┘
typ             └──────────┘
1063  
1064  /-- `image f s` is the forward image of `s` under `f`. -/
1065  def image (f : α → β) (s : finset α) : finset β := (s.1.map f).to_finset
id                            └────┘     └────┘       └─┘   └───────┘
src                             └────┘      └────┘         └─┘    └───────┘
typ                           └────┘     └────┘       └─┘   └───────┘
doc                             └────┘      └────┘          └─┘    └───────┘
1066  
1067  @[simp] theorem image_val (f : α → β) (s : finset α) : (image f s).1 = (s.1.map f).erase_dup := rfl
id                                            └────┘      └───┘        └─┘   └───────┘     └─┘
src                                             └────┘       └───┘           └─┘    └───────┘     └─┘
typ                                           └────┘      └───┘        └─┘   └───────┘     └─┘
doc    └──┘                                     └────┘       └───┘              └─┘    └───────┘
1068  
1069  @[simp] theorem image_empty (f : α → β) : (∅ : finset α).image f = ∅ := rfl
id                                               └────┘  └───┘        └─┘
src                                                └────┘   └───┘         └─┘
typ                                              └────┘  └───┘        └─┘
doc    └──┘                                         └────┘   └───┘
1070  
1071  variables {f : α → β} {s : finset α}
id                              └────┘
src                             └────┘
typ                             └────┘
doc                             └────┘
1072  
1073  @[simp] theorem mem_image {b : β} : b ∈ s.image f ↔ ∃ a ∈ s, f a = b :=
id                                        └────┘           
src                                          └────┘               
typ                                       └────┘           
doc    └──┘                                   └────┘
1074  by simp only [mem_def, image_val, mem_erase_dup, multiset.mem_map, exists_prop]
id                 └─────┘  └───────┘  └───────────┘  └──────────────┘  └─────────┘
src     └─────────┘└─────┘└┘└───────┘└┘└───────────┘└┘└──────────────┘└┘└─────────┘└─
typ     └─────────┘└─────┘└┘└───────┘└┘└───────────┘└┘└──────────────┘└┘└─────────┘└─
doc     └─────────┘       └┘         └┘             └┘                └┘           └─
txt     └─────────┘       └┘         └┘             └┘                └┘           └─
par     └─────────┘       └┘         └┘             └┘                └┘           └─
pid         └──┘└┘       └┘         └┘             └┘                └┘           
st     └─────────────────────────────────────────────────────────────────────────────
1075  
src  
typ  
doc  
txt  
par  
pid  
st   
1076  @[simp] theorem mem_image_of_mem (f : α → β) {a} {s : finset α} (h : a ∈ s) : f a ∈ s.image f :=
id                                                       └────┘                 └────┘ 
src                                                        └────┘                       └────┘
typ                                                      └────┘                 └────┘ 
doc    └──┘                                                └────┘                         └────┘
1077  mem_image.2 ⟨_, h, rfl⟩
id   └───────┘        └─┘
src  └───────┘         └─┘
typ  └───────┘        └─┘
1078  
1079  @[simp] lemma coe_image {f : α → β} : ↑(s.image f) = f '' ↑s :=
id                                        └────┘     └┘ 
src                                          └────┘       └┘ 
typ                                       └────┘     └┘ 
doc    └──┘                                   └────┘
1080  set.ext $ λ _, mem_image.trans $ by simp only [exists_prop]; refl
id   └─────┘       └───────┘└────┘                 └─────────┘
src  └─────┘        └───────┘└────┘      └─────────┘└─────────┘  └────
typ  └─────┘       └───────┘└────┘      └─────────┘└─────────┘  └────
doc                                      └─────────┘             └────
txt                                      └─────────┘             └────
par                                      └─────────┘             └────
pid                                          └──┘└┘                 
st                                      └──────────────────────────────
1081  
src  
typ  
doc  
txt  
par  
pid  
st   
1082  lemma nonempty.image (h : s.nonempty) (f : α → β) : (s.image f).nonempty :=
id                             └───────┘               └────┘  └──────┘
src                             └───────┘                  └────┘   └──────┘
typ                            └───────┘               └────┘  └──────┘
doc                             └───────┘                  └────┘   └──────┘
1083  let ⟨a, ha⟩ := h in ⟨f a, mem_image_of_mem f ha⟩
id   └─┘    └┘              └──────────────┘ 
src                            └──────────────┘
typ  └─┘    └┘              └──────────────┘ 
1084  
1085  theorem image_to_finset [decidable_eq α] {s : multiset α} : s.to_finset.image f = (s.map f).to_finset :=
id                            └──────────┘        └──────┘     └────────┘└────┘    └──┘  └───────┘
src                           └──────────┘         └──────┘       └────────┘└────┘      └──┘   └───────┘
typ                           └──────────┘        └──────┘     └────────┘└────┘    └──┘  └───────┘
doc                                                └──────┘       └────────┘└────┘       └──┘   └───────┘
1086  ext.2 $ λ _, by simp only [mem_image, multiset.mem_to_finset, exists_prop, multiset.mem_map]
id   └─┘                      └───────┘  └────────────────────┘  └─────────┘  └──────────────┘
src  └─┘            └─────────┘└───────┘└┘└────────────────────┘└┘└─────────┘└┘└──────────────┘└─
typ  └─┘           └─────────┘└───────┘└┘└────────────────────┘└┘└─────────┘└┘└──────────────┘└─
doc                  └─────────┘         └┘                      └┘           └┘                └─
txt                  └─────────┘         └┘                      └┘           └┘                └─
par                  └─────────┘         └┘                      └┘           └┘                └─
pid                      └──┘└┘         └┘                      └┘           └┘                
st                  └─────────────────────────────────────────────────────────────────────────────
1087  
src  
typ  
doc  
txt  
par  
pid  
st   
1088  @[simp] theorem image_val_of_inj_on (H : ∀x∈s, ∀y∈s, f x = f y → x = y) : (image f s).1 = s.1.map f :=
id                                                                  └───┘       └─┘  
src                                                                           └───┘          └─┘
typ                                                                 └───┘       └─┘  
doc    └──┘                                                                     └───┘             └─┘
1089  multiset.erase_dup_eq_self.2 (nodup_map_on H s.2)
id   └────────────────────────┘   └──────────┘  
src  └────────────────────────┘   └──────────┘    
typ  └────────────────────────┘   └──────────┘  
1090  
1091  theorem image_id [decidable_eq α] : s.image id = s :=
id                     └──────────┘     └────┘ └┘  
src                    └──────────┘       └────┘ └┘ 
typ                    └──────────┘     └────┘ └┘  
doc                                       └────┘
1092  ext.2 $ λ _, by simp only [mem_image, exists_prop, id, exists_eq_right]
id   └─┘                      └───────┘  └─────────┘  └┘  └─────────────┘
src  └─┘            └─────────┘└───────┘└┘└─────────┘└┘└┘└┘└─────────────┘└─
typ  └─┘           └─────────┘└───────┘└┘└─────────┘└┘└┘└┘└─────────────┘└─
doc                  └─────────┘         └┘           └┘  └┘               └─
txt                  └─────────┘         └┘           └┘  └┘               └─
par                  └─────────┘         └┘           └┘  └┘               └─
pid                      └──┘└┘         └┘           └┘  └┘               
st                  └────────────────────────────────────────────────────────
1093  
src  
typ  
doc  
txt  
par  
pid  
st   
1094  theorem image_image [decidable_eq γ] {g : β → γ} : (s.image f).image g = s.image (g ∘ f) :=
id                        └──────────┘                └────┘  └───┘    └────┘    
src                       └──────────┘                    └────┘   └───┘      └────┘    
typ                       └──────────┘                └────┘  └───┘    └────┘    
doc                                                       └────┘   └───┘       └────┘
1095  eq_of_veq $ by simp only [image_val, erase_dup_map_erase_dup_eq, multiset.map_map]
id   └───────┘                 └───────┘  └────────────────────────┘  └──────────────┘
src  └───────┘      └─────────┘└───────┘└┘└────────────────────────┘└┘└──────────────┘└─
typ  └───────┘      └─────────┘└───────┘└┘└────────────────────────┘└┘└──────────────┘└─
doc                 └─────────┘         └┘                          └┘                └─
txt                 └─────────┘         └┘                          └┘                └─
par                 └─────────┘         └┘                          └┘                └─
pid                     └──┘└┘         └┘                          └┘                
st                 └────────────────────────────────────────────────────────────────────
1096  
src  
typ  
doc  
txt  
par  
pid  
st   
1097  theorem image_subset_image {s₁ s₂ : finset α} (h : s₁ ⊆ s₂) : s₁.image f ⊆ s₂.image f :=
id                                       └────┘        └┘  └┘    └┘└────┘   └┘└────┘ 
src                                      └────┘                     └────┘      └────┘
typ                                      └────┘        └┘  └┘    └┘└────┘   └┘└────┘ 
doc                                      └────┘                      └────┘       └────┘
1098  by simp only [subset_def, image_val, subset_erase_dup', erase_dup_subset', multiset.map_subset_map h]
id                 └────────┘  └───────┘  └───────────────┘  └───────────────┘  └─────────────────────┘ 
src     └─────────┘└────────┘└┘└───────┘└┘└───────────────┘└┘└───────────────┘└┘└─────────────────────┘ └─
typ     └─────────┘└────────┘└┘└───────┘└┘└───────────────┘└┘└───────────────┘└┘└─────────────────────┘└─
doc     └─────────┘          └┘         └┘                 └┘                 └┘                        └─
txt     └─────────┘          └┘         └┘                 └┘                 └┘                        └─
par     └─────────┘          └┘         └┘                 └┘                 └┘                        └─
pid         └──┘└┘          └┘         └┘                 └┘                 └┘                        
st     └───────────────────────────────────────────────────────────────────────────────────────────────────
1099  
src  
typ  
doc  
txt  
par  
pid  
st   
1100  theorem image_mono (f : α → β) : monotone (finset.image f) := λ _ _, image_subset_image
id                                  └──────┘  └──────────┘           └────────────────┘
src                                   └──────┘  └──────────┘              └────────────────┘
typ                                 └──────┘  └──────────┘           └────────────────┘
doc                                   └──────┘  └──────────┘
1101  
1102  theorem image_filter {p : β → Prop} [decidable_pred p] :
id                                       └────────────┘ 
src                                       └────────────┘
typ                                      └────────────┘ 
1103    (s.image f).filter p = (s.filter (p ∘ f)).image f :=
id      └────┘  └────┘     └─────┘      └───┘  
src      └────┘   └────┘       └─────┘        └───┘
typ     └────┘  └────┘     └─────┘      └───┘  
doc      └────┘   └────┘        └─────┘         └───┘
1104  ext.2 $ λ b, by simp only [mem_filter, mem_image, exists_prop]; exact
id   └─┘                      └────────┘  └───────┘  └─────────┘
src  └─┘            └─────────┘└────────┘└┘└───────┘└┘└─────────┘  └────┘
typ  └─┘           └─────────┘└────────┘└┘└───────┘└┘└─────────┘  └────┘
doc                  └─────────┘          └┘         └┘             └────┘
txt                  └─────────┘          └┘         └┘             └────┘
par                  └─────────┘          └┘         └┘             └────┘
pid                      └──┘└┘          └┘         └┘                  
st                  └──────────────────────────────────────────────────────
1105  ⟨by rintro ⟨⟨x, h1, rfl⟩, h2⟩; exact ⟨x, ⟨h1, h2⟩, rfl⟩,
id                                            └┘  └┘   └─┘
src     └───────────────────────┘└──────┘  └┘   └┘  └─┘└─┘└──
typ     └───────────────────────┘└──────┘ └┘ └┘└┘└┘└─┘└─┘└──
doc     └───────────────────────┘└──────┘  └┘   └┘  └─┘   └──
txt     └───────────────────────┘└──────┘  └┘   └┘  └─┘   └──
par     └───────────────────────┘└──────┘  └┘   └┘  └─┘   └──
pid     └────────────────────────────────┘  └┘   └┘  └─┘   └──
st   ──┘└──────────────────────────────────────────────────┘└─
1106   by rintro ⟨x, ⟨h1, h2⟩, rfl⟩; exact ⟨⟨x, h1, rfl⟩, h2⟩⟩
id                                            └┘  └─┘   └┘
src    └───────────────────────┘└──────┘   └┘  └┘└─┘└─┘  └──
typ    └───────────────────────┘└──────┘  └┘└┘└┘└─┘└─┘└┘└──
doc    └───────────────────────┘└──────┘   └┘  └┘   └─┘  └──
txt    └───────────────────────┘└──────┘   └┘  └┘   └─┘  └──
par    └───────────────────────┘└──────┘   └┘  └┘   └─┘  └──
pid    └────────────────────────────────┘   └┘  └┘   └─┘  └┘
st   ──┘└──────────────────────────────────────────────────┘└─
1107  
src  
typ  
doc  
txt  
par  
pid  
st   
1108  theorem image_union [decidable_eq α] {f : α → β} (s₁ s₂ : finset α) : (s₁ ∪ s₂).image f = s₁.image f ∪ s₂.image f :=
id                        └──────────┘                      └────┘      └┘  └┘ └───┘    └┘└────┘   └┘└────┘ 
src                       └──────────┘                         └────┘              └───┘       └────┘      └────┘
typ                       └──────────┘                      └────┘      └┘  └┘ └───┘    └┘└────┘   └┘└────┘ 
doc                                                            └────┘               └───┘        └────┘       └────┘
1109  ext.2 $ λ _, by simp only [mem_image, mem_union, exists_prop, or_and_distrib_right, exists_or_distrib]
id   └─┘                      └───────┘  └───────┘  └─────────┘  └──────────────────┘  └───────────────┘
src  └─┘            └─────────┘└───────┘└┘└───────┘└┘└─────────┘└┘└──────────────────┘└┘└───────────────┘└─
typ  └─┘           └─────────┘└───────┘└┘└───────┘└┘└─────────┘└┘└──────────────────┘└┘└───────────────┘└─
doc                  └─────────┘         └┘         └┘           └┘                    └┘                 └─
txt                  └─────────┘         └┘         └┘           └┘                    └┘                 └─
par                  └─────────┘         └┘         └┘           └┘                    └┘                 └─
pid                      └──┘└┘         └┘         └┘           └┘                    └┘                 
st                  └───────────────────────────────────────────────────────────────────────────────────────
1110  
src  
typ  
doc  
txt  
par  
pid  
st   
1111  theorem image_inter [decidable_eq α] (s₁ s₂ : finset α) (hf : ∀x y, f x = f y → x = y) : (s₁ ∩ s₂).image f = s₁.image f ∩ s₂.image f :=
id                        └──────────┘            └────┘                           └┘  └┘ └───┘    └┘└────┘   └┘└────┘ 
src                       └──────────┘             └────┘                                           └───┘       └────┘      └────┘
typ                       └──────────┘            └────┘                           └┘  └┘ └───┘    └┘└────┘   └┘└────┘ 
doc                                                └────┘                                              └───┘        └────┘       └────┘
1112  ext.2 $ by simp only [mem_image, exists_prop, mem_inter]; exact λ b,
id   └─┘                  └───────┘  └─────────┘  └───────┘
src  └─┘       └─────────┘└───────┘└┘└─────────┘└┘└───────┘  └────┘ └──┘
typ  └─┘       └─────────┘└───────┘└┘└─────────┘└┘└───────┘  └────┘ └──┘
doc             └─────────┘         └┘           └┘           └────┘ └──┘
txt             └─────────┘         └┘           └┘           └────┘ └──┘
par             └─────────┘         └┘           └┘           └────┘ └──┘
pid                 └──┘└┘         └┘           └┘                 └──┘
st             └──────────────────────────────────────────────────────────
1113  ⟨λ ⟨a, ⟨m₁, m₂⟩, e⟩, ⟨⟨a, m₁, e⟩, ⟨a, m₂, e⟩⟩,
id          └┘  └┘   
src    └┘ └┘   └┘  └─┘ └─┘   └┘  └┘ └─┘  └┘  └┘ └───
typ    └┘└┘ └┘└┘└┘└─┘└─┘   └┘  └┘ └─┘  └┘  └┘ └───
doc    └┘ └┘   └┘  └─┘ └─┘   └┘  └┘ └─┘  └┘  └┘ └───
txt    └┘ └┘   └┘  └─┘ └─┘   └┘  └┘ └─┘  └┘  └┘ └───
par    └┘ └┘   └┘  └─┘ └─┘   └┘  └┘ └─┘  └┘  └┘ └───
pid    └┘ └┘   └┘  └─┘ └─┘   └┘  └┘ └─┘  └┘  └┘ └───
st   ───────────────────────────────────────────────
1114   λ ⟨⟨a, m₁, e₁⟩, ⟨a', m₂, e₂⟩⟩, ⟨a, ⟨m₁, hf _ _ (e₂.trans e₁.symm) ▸ m₂⟩, e₁⟩⟩.
id          └┘  └┘        └┘  └┘             └┘        └────┘   └───┘  
src   └┘  └┘  └┘  └─┘   └┘  └┘  └──┘  └┘   └┘  └───┘   └────┘  └───┘└┘  └─┘  └┘
typ   └┘ └┘└┘└┘└┘└─┘   └┘└┘└┘└┘└──┘  └┘   └┘└┘└───┘   └────┘  └───┘└┘  └─┘  └┘
doc   └┘  └┘  └┘  └─┘   └┘  └┘  └──┘  └┘   └┘  └───┘                └┘   └─┘  └┘
txt   └┘  └┘  └┘  └─┘   └┘  └┘  └──┘  └┘   └┘  └───┘                └┘   └─┘  └┘
par   └┘  └┘  └┘  └─┘   └┘  └┘  └──┘  └┘   └┘  └───┘                └┘   └─┘  └┘
pid   └┘  └┘  └┘  └─┘   └┘  └┘  └──┘  └┘   └┘  └───┘                └┘   └─┘  └┘
st   ─────────────────────────────────────────────────────────────────────────────┘
1115  
1116  @[simp] theorem image_singleton (f : α → β) (a : α) : (singleton a).image f = singleton (f a) :=
id                                                       └───────┘  └───┘    └───────┘   
src                                                         └───────┘   └───┘     └───────┘
typ                                                      └───────┘  └───┘    └───────┘   
doc    └──┘                                                 └───────┘   └───┘      └───────┘
1117  ext.2 $ λ x, by simpa only [mem_image, exists_prop, mem_singleton, exists_eq_left] using eq_comm
id   └─┘                       └───────┘  └─────────┘  └───────────┘  └────────────┘        └─────┘
src  └─┘            └──────────┘└───────┘└┘└─────────┘└┘└───────────┘└┘└────────────┘└──────┘└─────┘
typ  └─┘           └──────────┘└───────┘└┘└─────────┘└┘└───────────┘└┘└────────────┘└──────┘└─────┘
doc                  └──────────┘         └┘           └┘             └┘              └──────┘       
txt                  └──────────┘         └┘           └┘             └┘              └──────┘       
par                  └──────────┘         └┘           └┘             └┘              └──────┘       
pid                       └──┘└┘         └┘           └┘             └┘              └────┘       
st                  └─────────────────────────────────────────────────────────────────────────────────
1118  
src  
typ  
doc  
txt  
par  
pid  
st   
1119  @[simp] theorem image_insert [decidable_eq α] (f : α → β) (a : α) (s : finset α) :
id                                 └──────────┘                         └────┘ 
src                                └──────────┘                             └────┘
typ                                └──────────┘                         └────┘ 
doc    └──┘                                                                 └────┘
1120    (insert a s).image f = insert (f a) (s.image f) :=
id      └────┘   └───┘    └────┘      └────┘ 
src     └────┘     └───┘     └────┘         └────┘
typ     └────┘   └───┘    └────┘      └────┘ 
doc                └───┘                     └────┘
1121  by simp only [insert_eq, insert_empty_eq_singleton, image_singleton, image_union]
id                 └───────┘  └───────────────────────┘  └─────────────┘  └─────────┘
src     └─────────┘└───────┘└┘└───────────────────────┘└┘└─────────────┘└┘└─────────┘└─
typ     └─────────┘└───────┘└┘└───────────────────────┘└┘└─────────────┘└┘└─────────┘└─
doc     └─────────┘         └┘                         └┘               └┘           └─
txt     └─────────┘         └┘                         └┘               └┘           └─
par     └─────────┘         └┘                         └┘               └┘           └─
pid         └──┘└┘         └┘                         └┘               └┘           
st     └───────────────────────────────────────────────────────────────────────────────
1122  
src  
typ  
doc  
txt  
par  
pid  
st   
1123  @[simp] theorem image_eq_empty : s.image f = ∅ ↔ s = ∅ :=
id                                    └────┘       
src                                    └────┘         
typ                                   └────┘       
doc    └──┘                            └────┘
1124  ⟨λ h, eq_empty_of_forall_not_mem $
id        └────────────────────────┘
src        └────────────────────────┘
typ       └────────────────────────┘
1125   λ a m, ne_empty_of_mem (mem_image_of_mem _ m) h, λ e, e.symm ▸ rfl⟩
id         └─────────────┘  └──────────────┘           └───┘  └─┘
src          └─────────────┘  └──────────────┘               └───┘  └─┘
typ        └─────────────┘  └──────────────┘           └───┘  └─┘
1126  
1127  lemma attach_image_val [decidable_eq α] {s : finset α} : s.attach.image subtype.val = s :=
id                           └──────────┘        └────┘     └─────┘└────┘ └─────────┘  
src                          └──────────┘         └────┘       └─────┘└────┘ └─────────┘ 
typ                          └──────────┘        └────┘     └─────┘└────┘ └─────────┘  
doc                                               └────┘       └─────┘└────┘
1128  eq_of_veq $ by rw [image_val, attach_val, multiset.attach_map_val, erase_dup_eq_self]
id   └───────┘          └───────┘  └────────┘  └─────────────────────┘  └───────────────┘
src  └───────┘      └──┘└───────┘└┘└────────┘└┘└─────────────────────┘└┘└───────────────┘└─
typ  └───────┘      └──┘└───────┘└┘└────────┘└┘└─────────────────────┘└┘└───────────────┘└─
doc                 └──┘         └┘          └┘                       └┘                 └─
txt                 └──┘         └┘          └┘                       └┘                 └─
par                 └──┘         └┘          └┘                       └┘                 └─
pid                   └┘         └┘          └┘                       └┘                 
st                 └────────────┘└──────────┘└───────────────────────┘└─────────────────┘
1129  
src  
typ  
doc  
txt  
par  
pid  
st   
1130  @[simp] lemma attach_insert [decidable_eq α] {a : α} {s : finset α} :
id                                └──────────┘               └────┘ 
src                               └──────────┘                 └────┘
typ                               └──────────┘               └────┘ 
doc    └──┘                                                    └────┘
1131    attach (insert a s) = insert (⟨a, mem_insert_self a s⟩ : {x // x ∈ insert a s})
id     └────┘  └────┘     └────┘     └─────────────┘            └────┘  
src    └────┘  └────┘       └────┘      └─────────────┘                └────┘
typ    └────┘  └────┘     └────┘     └─────────────┘            └────┘  
doc    └────┘
1132      ((attach s).image (λx, ⟨x.1, mem_insert_of_mem x.2⟩)) :=
id         └────┘  └───┘          └───────────────┘ 
src        └────┘   └───┘            └───────────────┘  
typ        └────┘  └───┘          └───────────────┘ 
doc        └────┘   └───┘
1133  ext.2 $ λ ⟨x, hx⟩, ⟨or.cases_on (mem_insert.1 hx)
id   └─┘        └┘    └─────────┘  └────────┘
src  └─┘                └─────────┘  └────────┘
typ  └─┘        └┘    └─────────┘  └────────┘
1134    (assume h : x = a, λ _, mem_insert.2 $ or.inl $ subtype.eq h)
id                          └────────┘    └────┘   └────────┘ 
src                           └────────┘    └────┘   └────────┘
typ                         └────────┘    └────┘   └────────┘ 
1135    (assume h : x ∈ s, λ _, mem_insert_of_mem $ mem_image.2 $ ⟨⟨x, h⟩, mem_attach _ _, subtype.eq rfl⟩),
id                          └───────────────┘   └───────┘            └────────┘      └────────┘ └─┘
src                           └───────────────┘   └───────┘             └────────┘      └────────┘ └─┘
typ                         └───────────────┘   └───────┘            └────────┘      └────────┘ └─┘
1136  λ _, finset.mem_attach _ _⟩
id       └───────────────┘
src       └───────────────┘
typ      └───────────────┘
1137  
1138  theorem map_eq_image (f : α ↪ β) (s : finset α) : s.map f = s.image f :=
id                                      └────┘     └──┘   └────┘ 
src                                       └────┘       └──┘     └────┘
typ                                     └────┘     └──┘   └────┘ 
doc                                        └────┘                 └────┘
1139  eq_of_veq $ (multiset.erase_dup_eq_self.2 (s.map f).2).symm
id   └───────┘    └────────────────────────┘   └──┘    └──┘
src  └───────┘    └────────────────────────┘    └──┘     └──┘
typ  └───────┘    └────────────────────────┘   └──┘    └──┘
1140  
1141  lemma image_const {s : finset α} (h : s.nonempty) (b : β) : s.image (λa, b) = singleton b :=
id                          └────┘        └───────┘           └────┘        └───────┘ 
src                         └────┘          └───────┘             └────┘          └───────┘
typ                         └────┘        └───────┘           └────┘        └───────┘ 
doc                         └────┘          └───────┘             └────┘           └───────┘
1142  ext.2 $ assume b', by simp only [mem_image, exists_prop, exists_and_distrib_right,
id   └─┘           └┘                └───────┘  └─────────┘  └──────────────────────┘
src  └─┘                  └─────────┘└───────┘└┘└─────────┘└┘└──────────────────────┘└─
typ  └─┘           └┘     └─────────┘└───────┘└┘└─────────┘└┘└──────────────────────┘└─
doc                        └─────────┘         └┘           └┘                        └─
txt                        └─────────┘         └┘           └┘                        └─
par                        └─────────┘         └┘           └┘                        └─
pid                            └──┘└┘         └┘           └┘                        └─
st                        └─────────────────────────────────────────────────────────────
1143    h.bex, true_and, mem_singleton, eq_comm]
id            └──────┘  └───────────┘  └─────┘
src  ─┘     └┘└──────┘└┘└───────────┘└┘└─────┘└─
typ  ─┘└───┘└┘└──────┘└┘└───────────┘└┘└─────┘└─
doc  ─┘     └┘        └┘             └┘       └─
txt  ─┘     └┘        └┘             └┘       └─
par  ─┘     └┘        └┘             └┘       └─
pid  ─┘     └┘        └┘             └┘       
st   ───────────────────────────────────────────
1144  
src  
typ  
doc  
txt  
par  
pid  
st   
1145  protected def subtype {α} (p : α → Prop) [decidable_pred p] (s : finset α) : finset (subtype p) :=
id                                            └────────────┘        └────┘     └────┘  └─────┘ 
src                                            └────────────┘         └────┘      └────┘  └─────┘
typ                                           └────────────┘        └────┘     └────┘  └─────┘ 
doc                                                                   └────┘      └────┘
1146  (s.filter p).attach.map ⟨λ x, ⟨x.1, (finset.mem_filter.1 x.2).2⟩,
id    └─────┘  └────┘ └─┘            └───────────────┘    
src    └─────┘   └────┘ └─┘              └───────────────┘     
typ   └─────┘  └────┘ └─┘            └───────────────┘    
doc    └─────┘   └────┘
1147  λ x y H, subtype.eq $ subtype.mk.inj H⟩
id         └────────┘   └────────────┘ 
src           └────────┘   └────────────┘
typ        └────────┘   └────────────┘ 
1148  
1149  @[simp] lemma mem_subtype {p : α → Prop} [decidable_pred p] {s : finset α} :
id                                            └────────────┘        └────┘ 
src                                            └────────────┘         └────┘
typ                                           └────────────┘        └────┘ 
doc    └──┘                                                           └────┘
1150    ∀{a : subtype p}, a ∈ s.subtype p ↔ a.val ∈ s
id          └─────┘      └──────┘   └──┘  
src          └─────┘         └──────┘     └──┘ 
typ         └─────┘      └──────┘   └──┘  
1151  | ⟨a, ha⟩ := by simp [finset.subtype, ha]
id                         └────────────┘  └┘
src                  └────┘└────────────┘└┘  └─
typ                  └────┘└────────────┘└┘└┘└─
doc                  └────┘              └┘  └─
txt                  └────┘              └┘  └─
par                  └────┘              └┘  └─
pid                                    └┘  
st                  └──────────────────────────
1152  
src  
typ  
doc  
txt  
par  
pid  
st   
1153  lemma subset_image_iff [decidable_eq α] {f : α → β}
id                           └──────────┘           
src                          └──────────┘
typ                          └──────────┘           
1154    {s : finset β} {t : set α} : ↑s ⊆ f '' t ↔ ∃s' : finset α, ↑s' ⊆ t ∧ s'.image f = s :=
id          └────┘        └─┘        └┘        └────┘  └┘    └┘└────┘   
src         └────┘         └─┘           └┘         └────┘            └────┘   
typ         └────┘        └─┘        └┘        └────┘  └┘    └┘└────┘   
doc         └────┘                                      └────┘                └────┘
1155  begin
st   └─────
1156    split, swap,
src    └───┘  └──┘
typ    └───┘  └──┘
doc    └───┘  └──┘
txt    └───┘  └──┘
par    └───┘  └──┘
st   ──────┘└────┘└─
1157    { rintro ⟨s, hs, rfl⟩, rw [coe_image], exact set.image_subset f hs },
id                                └───────┘         └──────────────┘  └┘
src      └─────────────────┘  └──┘└───────┘  └────┘└──────────────┘   
typ      └─────────────────┘  └──┘└───────┘  └────┘└──────────────┘└┘
doc      └─────────────────┘  └──┘           └────┘                   
txt      └─────────────────┘  └──┘           └────┘                   
par      └─────────────────┘  └──┘           └────┘                   
pid            └───────────┘    └┘                                   
st   ───┘└─────────────────┘└─────────────┘└─────────────────────────────┘└┘
1158    intro h, induction s using finset.induction with a s has ih h,
id                        
src    └─────┘  └────────┘ └───────────────────────────────────────┘
typ    └─────┘  └────────┘└───────────────────────────────────────┘
doc    └─────┘  └────────┘ └───────────────────────────────────────┘
txt    └─────┘  └────────┘ └───────────────────────────────────────┘
par    └─────┘  └────────┘ └───────────────────────────────────────┘
pid         └┘            └─────────────────────┘└────────────────┘
st   ────────┘└────────────────────────────────────────────────────┘└─
1159    { exact ⟨∅, set.empty_subset _, finset.image_empty _⟩ },
id                └──────────────┘    └────────────────┘
src      └────┘ └┘└──────────────┘└──┘└────────────────┘└──┘
typ      └────┘ └┘└──────────────┘└──┘└────────────────┘└──┘
doc      └────┘  └┘                └──┘                  └──┘
txt      └────┘  └┘                └──┘                  └──┘
par      └────┘  └┘                └──┘                  └──┘
pid             └┘                └──┘                  └─┘
st   ───┘└──────────────────────────────────────────────────┘└┘
1160    rw [finset.coe_insert, set.insert_subset] at h,
id         └───────────────┘  └───────────────┘
src    └──┘└───────────────┘└┘└───────────────┘└────┘
typ    └──┘└───────────────┘└┘└───────────────┘└────┘
doc    └──┘                 └┘                 └────┘
txt    └──┘                 └┘                 └────┘
par    └──┘                 └┘                 └────┘
pid      └┘                 └┘                 └───┘
st   ──────────────────────┘└─────────────────┘└───┘└─
1161    rcases ih h.2 with ⟨s', hst, hsi⟩,
id            └┘ 
src    └─────┘   └────────────────────┘
typ    └─────┘└┘└────────────────────┘
doc    └─────┘   └────────────────────┘
txt    └─────┘   └────────────────────┘
par    └─────┘   └────────────────────┘
pid             └────────────────────┘
st   ──────────────────────────────────┘└─
1162    rcases h.1 with ⟨x, hxt, rfl⟩,
id            
src    └─────┘ └───────────────────┘
typ    └─────┘└───────────────────┘
doc    └─────┘ └───────────────────┘
txt    └─────┘ └───────────────────┘
par    └─────┘ └───────────────────┘
pid           └───────────────────┘
st   ──────────────────────────────┘└─
1163    refine ⟨insert x s', _, _⟩,
id             └────┘  └┘
src    └─────┘ └────┘   └─────┘
typ    └─────┘ └────┘└┘└─────┘
doc    └─────┘          └─────┘
txt    └─────┘          └─────┘
par    └─────┘          └─────┘
pid                    └─────┘
st   ───────────────────────────┘└─
1164    { rw [finset.coe_insert, set.insert_subset], exact ⟨hxt, hst⟩ },
id           └───────────────┘  └───────────────┘          └─┘  └─┘
src      └──┘└───────────────┘└┘└───────────────┘  └────┘    └┘   └┘
typ      └──┘└───────────────┘└┘└───────────────┘  └────┘ └─┘└┘└─┘└┘
doc      └──┘                 └┘                   └────┘    └┘   └┘
txt      └──┘                 └┘                   └────┘    └┘   └┘
par      └──┘                 └┘                   └────┘    └┘   └┘
pid        └┘                 └┘                            └┘   
st   ───┘└───────────────────┘└─────────────────┘└──────────────────┘└┘
1165    rw [finset.image_insert, hsi]
id         └─────────────────┘  └─┘
src    └──┘└─────────────────┘└┘   └┘
typ    └──┘└─────────────────┘└┘└─┘└┘
doc    └──┘                   └┘   └┘
txt    └──┘                   └┘   └┘
par    └──┘                   └┘   └┘
pid      └┘                   └┘   
st   ────────────────────────┘└───┘
1166  end
st   └─┘
1167  
1168  end image
1169  
1170  /-! ### card -/
1171  section card
1172  
1173  /-- `card s` is the cardinality (number of elements) of `s`. -/
1174  def card (s : finset α) : nat := s.1.card
id                 └────┘     └─┘     └──┘
src                └────┘      └─┘      └──┘
typ                └────┘     └─┘     └──┘
doc                └────┘                └──┘
1175  
1176  theorem card_def (s : finset α) : s.card = s.1.card := rfl
id                         └────┘     └───┘   └──┘     └─┘
src                        └────┘       └───┘    └──┘     └─┘
typ                        └────┘     └───┘   └──┘     └─┘
doc                        └────┘       └───┘      └──┘
1177  
1178  @[simp] theorem card_empty : card (∅ : finset α) = 0 := rfl
id                                └──┘     └────┘         └─┘
src                               └──┘     └────┘          └─┘
typ                               └──┘     └────┘         └─┘
doc    └──┘                       └──┘      └────┘
1179  
1180  @[simp] theorem card_eq_zero {s : finset α} : card s = 0 ↔ s = ∅ :=
id                                     └────┘     └──┘        
src                                    └────┘      └──┘          
typ                                    └────┘     └──┘        
doc    └──┘                            └────┘      └──┘
1181  card_eq_zero.trans val_eq_zero
id   └──────────┘└────┘ └─────────┘
src  └──────────┘└────┘ └─────────┘
typ  └──────────┘└────┘ └─────────┘
1182  
1183  theorem card_pos {s : finset α} : 0 < card s ↔ s.nonempty :=
id                         └────┘        └──┘   └───────┘
src                        └────┘         └──┘     └───────┘
typ                        └────┘        └──┘   └───────┘
doc                        └────┘          └──┘      └───────┘
1184  pos_iff_ne_zero.trans $ (not_congr card_eq_zero).trans nonempty_iff_ne_empty.symm
id   └─────────────┘└────┘    └───────┘ └──────────┘ └───┘  └───────────────────┘└───┘
src  └─────────────┘└────┘    └───────┘ └──────────┘ └───┘  └───────────────────┘└───┘
typ  └─────────────┘└────┘    └───────┘ └──────────┘ └───┘  └───────────────────┘└───┘
1185  
1186  theorem card_ne_zero_of_mem {s : finset α} {a : α} (h : a ∈ s) : card s ≠ 0 :=
id                                    └────┘                     └──┘  
src                                   └────┘                         └──┘   
typ                                   └────┘                     └──┘  
doc                                   └────┘                          └──┘
1187  (not_congr card_eq_zero).2 (ne_empty_of_mem h)
id    └───────┘ └──────────┘    └─────────────┘ 
src   └───────┘ └──────────┘    └─────────────┘
typ   └───────┘ └──────────┘    └─────────────┘ 
1188  
1189  theorem card_eq_one {s : finset α} : s.card = 1 ↔ ∃ a, s = finset.singleton a :=
id                            └────┘     └───┘         └──────────────┘ 
src                           └────┘       └───┘           └──────────────┘
typ                           └────┘     └───┘         └──────────────┘ 
doc                           └────┘       └───┘                └──────────────┘
1190  by cases s; simp [multiset.card_eq_one, finset.singleton, finset.card]
id                    └──────────────────┘  └──────────────┘  └─────────┘
src     └────┘   └────┘└──────────────────┘└┘└──────────────┘└┘└─────────┘└─
typ     └────┘  └────┘└──────────────────┘└┘└──────────────┘└┘└─────────┘└─
doc     └────┘   └────┘                    └┘└──────────────┘└┘└─────────┘└─
txt     └────┘   └────┘                    └┘                └┘           └─
par     └────┘   └────┘                    └┘                └┘           └─
pid                                     └┘                └┘           
st     └────────────────────────────────────────────────────────────────────
1191  
src  
typ  
doc  
txt  
par  
pid  
st   
1192  @[simp] theorem card_insert_of_not_mem [decidable_eq α]
id                                           └──────────┘ 
src                                          └──────────┘
typ                                          └──────────┘ 
doc    └──┘
1193    {a : α} {s : finset α} (h : a ∉ s) : card (insert a s) = card s + 1 :=
id                 └────┘              └──┘  └────┘     └──┘  
src                 └────┘                 └──┘  └────┘       └──┘   
typ                └────┘              └──┘  └────┘     └──┘  
doc                 └────┘                  └──┘                └──┘
1194  by simpa only [card_cons, card, insert_val] using
id                  └───────┘  └──┘  └────────┘
src     └──────────┘└───────┘└┘└──┘└┘└────────┘└──────┘
typ     └──────────┘└───────┘└┘└──┘└┘└────────┘└──────┘
doc     └──────────┘         └┘└──┘└┘          └──────┘
txt     └──────────┘         └┘    └┘          └──────┘
par     └──────────┘         └┘    └┘          └──────┘
pid          └──┘└┘         └┘    └┘          └────┘
st     └───────────────────────────────────────────────
1195  congr_arg multiset.card (ndinsert_of_not_mem h)
id   └───────┘ └───────────┘  └─────────────────┘ 
src  └───────┘└───────────┘ └─────────────────┘ └─
typ  └───────┘└───────────┘ └─────────────────┘└─
doc           └───────────┘                     └─
txt                                             └─
par                                             └─
pid                                             
st   ────────────────────────────────────────────────
1196  
src  
typ  
doc  
txt  
par  
pid  
st   
1197  theorem card_insert_le [decidable_eq α] (a : α) (s : finset α) : card (insert a s) ≤ card s + 1 :=
id                           └──────────┘               └────┘     └──┘  └────┘     └──┘  
src                          └──────────┘                 └────┘      └──┘  └────┘       └──┘   
typ                          └──────────┘               └────┘     └──┘  └────┘     └──┘  
doc                                                       └────┘      └──┘                └──┘
1198  by by_cases a ∈ s; [{rw [insert_eq_of_mem h], apply nat.le_add_right},
id                        └──────────────┘          └──────────────┘
src     └───────┘     └──┘└──────────────┘   └────┘└──────────────┘
typ     └───────┘   └──┘└──────────────┘  └────┘└──────────────┘
doc     └───────┘       └──┘                   └────┘
txt     └───────┘       └──┘                   └────┘
par     └───────┘       └──┘                   └────┘
pid                      └┘                        
st     └────────────────┘└─────────────────────┘└───────────────────────┘└┘
1199  rw [card_insert_of_not_mem h]]
id       └────────────────────┘ 
src  └──┘└────────────────────┘ 
typ  └──┘└────────────────────┘
doc  └──┘                       
txt  └──┘                       
par  └──┘                       
pid    └┘                       
st   ───┘└──────────────────────┘
1200  
1201  @[simp] theorem card_singleton (a : α) : card (singleton a) = 1 := card_singleton _
id                                           └──┘  └───────┘         └────────────┘
src                                           └──┘  └───────┘          └────────────┘
typ                                          └──┘  └───────┘         └────────────┘
doc    └──┘                                   └──┘  └───────┘
1202  
1203  theorem card_erase_of_mem [decidable_eq α] {a : α} {s : finset α} : a ∈ s → card (erase s a) = pred (card s) := card_erase_of_mem
id                              └──────────┘               └────┘          └──┘  └───┘     └──┘  └──┘      └───────────────┘
src                             └──────────┘                 └────┘             └──┘  └───┘       └──┘  └──┘       └───────────────┘
typ                             └──────────┘               └────┘          └──┘  └───┘     └──┘  └──┘      └───────────────┘
doc                                                          └────┘              └──┘  └───┘              └──┘
1204  
1205  theorem card_erase_lt_of_mem [decidable_eq α] {a : α} {s : finset α} : a ∈ s → card (erase s a) < card s := card_erase_lt_of_mem
id                                 └──────────┘               └────┘          └──┘  └───┘     └──┘     └──────────────────┘
src                                └──────────┘                 └────┘             └──┘  └───┘       └──┘      └──────────────────┘
typ                                └──────────┘               └────┘          └──┘  └───┘     └──┘     └──────────────────┘
doc                                                             └────┘              └──┘  └───┘        └──┘
1206  
1207  theorem card_erase_le [decidable_eq α] {a : α} {s : finset α} : card (erase s a) ≤ card s := card_erase_le
id                          └──────────┘               └────┘     └──┘  └───┘     └──┘     └───────────┘
src                         └──────────┘                 └────┘      └──┘  └───┘       └──┘      └───────────┘
typ                         └──────────┘               └────┘     └──┘  └───┘     └──┘     └───────────┘
doc                                                      └────┘      └──┘  └───┘        └──┘
1208  
1209  @[simp] theorem card_range (n : ℕ) : card (range n) = n := card_range n
id                                       └──┘  └───┘        └────────┘ 
src                                      └──┘  └───┘          └────────┘
typ                                      └──┘  └───┘        └────────┘ 
doc    └──┘                               └──┘  └───┘
1210  
1211  @[simp] theorem card_attach {s : finset α} : card (attach s) = card s := multiset.card_attach
id                                    └────┘     └──┘  └────┘    └──┘     └──────────────────┘
src                                   └────┘      └──┘  └────┘     └──┘      └──────────────────┘
typ                                   └────┘     └──┘  └────┘    └──┘     └──────────────────┘
doc    └──┘                           └────┘      └──┘  └────┘      └──┘
1212  
1213  theorem card_image_of_inj_on [decidable_eq β] {f : α → β} {s : finset α}
id                                 └──────────┘                  └────┘ 
src                                └──────────┘                     └────┘
typ                                └──────────┘                  └────┘ 
doc                                                                 └────┘
1214    (H : ∀x∈s, ∀y∈s, f x = f y → x = y) : card (image f s) = card s :=
id                               └──┘  └───┘     └──┘ 
src                                        └──┘  └───┘       └──┘
typ                              └──┘  └───┘     └──┘ 
doc                                          └──┘  └───┘        └──┘
1215  by simp only [card, image_val_of_inj_on H, card_map]
id                 └──┘  └─────────────────┘   └──────┘
src     └─────────┘└──┘└┘└─────────────────┘ └┘└──────┘└─
typ     └─────────┘└──┘└┘└─────────────────┘└┘└──────┘└─
doc     └─────────┘└──┘└┘                    └┘        └─
txt     └─────────┘    └┘                    └┘        └─
par     └─────────┘    └┘                    └┘        └─
pid         └──┘└┘    └┘                    └┘        
st     └──────────────────────────────────────────────────
1216  
src  
typ  
doc  
txt  
par  
pid  
st   
1217  theorem card_image_of_injective [decidable_eq β] {f : α → β} (s : finset α)
id                                    └──────────┘                  └────┘ 
src                                   └──────────┘                     └────┘
typ                                   └──────────┘                  └────┘ 
doc                                                                    └────┘
1218    (H : function.injective f) : card (image f s) = card s :=
id          └────────────────┘     └──┘  └───┘     └──┘ 
src         └────────────────┘      └──┘  └───┘       └──┘
typ         └────────────────┘     └──┘  └───┘     └──┘ 
doc                                 └──┘  └───┘        └──┘
1219  card_image_of_inj_on $ λ x _ y _ h, H h
id   └──────────────────┘            
src  └──────────────────┘
typ  └──────────────────┘            
1220  
1221  @[simp] lemma card_map {α β} [decidable_eq β] (f : α ↪ β) {s : finset α} : (s.map f).card = s.card :=
id                                 └──────────┘                 └────┘      └──┘  └──┘   └───┘
src                                └──────────┘                    └────┘        └──┘   └──┘    └───┘
typ                                └──────────┘                 └────┘      └──┘  └──┘   └───┘
doc    └──┘                                                         └────┘               └──┘     └───┘
1222  by rw [map_eq_image, card_image_of_injective]; exact f.2
id          └──────────┘  └─────────────────────┘         
src     └──┘└──────────┘└┘└─────────────────────┘  └────┘ └──
typ     └──┘└──────────┘└┘└─────────────────────┘  └────┘└──
doc     └──┘            └┘                         └────┘ └──
txt     └──┘            └┘                         └────┘ └──
par     └──┘            └┘                         └────┘ └──
pid       └┘            └┘                               └──
st     └───────────────┘└───────────────────────┘└───────────
1223  
src  
typ  
doc  
txt  
par  
pid  
st   
1224  lemma card_eq_of_bijective [decidable_eq α] {s : finset α} {n : ℕ}
id                               └──────────┘        └────┘        
src                              └──────────┘         └────┘         
typ                              └──────────┘        └────┘        
doc                                                   └────┘
1225    (f : ∀i, i < n → α)
id                  
src               
typ                 
1226    (hf : ∀a∈s, ∃i, ∃h:i<n, f i h = a) (hf' : ∀i (h : i < n), f i h ∈ s)
id                                                
src                                                             
typ                                               
1227    (f_inj : ∀i j (hi : i < n) (hj : j < n), f i hi = f j hj → i = j) :
id                                        └┘    └┘     
src                                                              
typ                                       └┘    └┘     
1228    card s = n :=
id     └──┘   
src    └──┘   
typ    └──┘   
doc    └──┘
1229  have ∀ (a : α), a ∈ s ↔ ∃i (hi : i ∈ range n), f i (mem_range.1 hi) = a,
id                               └───┘      └───────┘  └┘   
src                                   └───┘         └───────┘      
typ                              └───┘      └───────┘  └┘   
doc                                       └───┘
1230    from assume a, ⟨assume ha, let ⟨i, hi, eq⟩ := hf a ha in ⟨i, mem_range.2 hi, eq⟩,
id                           └┘  └─┘    └┘  └┘     └┘  └┘        └───────┘
src                                           └┘                    └───────┘
typ                          └┘  └─┘    └┘  └┘     └┘  └┘        └───────┘
1231      assume ⟨i, hi, eq⟩, eq ▸ hf' i (mem_range.1 hi)⟩,
id                └┘  └┘       └─┘    └───────┘
src                     └┘              └───────┘
typ               └┘  └┘       └─┘    └───────┘
1232  have s = ((range n).attach.image $ λi, f i.1 (mem_range.1 i.2)),
id            └───┘  └────┘ └───┘           └───────┘  
src            └───┘   └────┘ └───┘              └───────┘   
typ           └───┘  └────┘ └───┘           └───────┘  
doc             └───┘   └────┘ └───┘
1233    by simpa only [ext, mem_image, exists_prop, subtype.exists, mem_attach, true_and],
id                    └─┘  └───────┘  └─────────┘  └────────────┘  └────────┘  └──────┘
src       └──────────┘└─┘└┘└───────┘└┘└─────────┘└┘└────────────┘└┘└────────┘└┘└──────┘
typ       └──────────┘└─┘└┘└───────┘└┘└─────────┘└┘└────────────┘└┘└────────┘└┘└──────┘
doc       └──────────┘   └┘         └┘           └┘              └┘          └┘        
txt       └──────────┘   └┘         └┘           └┘              └┘          └┘        
par       └──────────┘   └┘         └┘           └┘              └┘          └┘        
pid            └──┘└┘   └┘         └┘           └┘              └┘          └┘        
st       └─────────────────────────────────────────────────────────────────────────────┘
1234  calc card s = card ((range n).attach.image $ λi, f i.1 (mem_range.1 i.2)) :
id        └──┘    └──┘   └───┘  └────┘ └───┘           └───────┘  
src       └──┘     └──┘   └───┘   └────┘ └───┘              └───────┘   
typ       └──┘    └──┘   └───┘  └────┘ └───┘           └───────┘  
doc       └──┘     └──┘   └───┘   └────┘ └───┘
1235      by rw [this]
id              └──┘
src         └──┘    └─
typ         └──┘└──┘└─
doc         └──┘    └─
txt         └──┘    └─
par         └──┘    └─
pid           └┘    
st         └───────┘
1236    ... = card ((range n).attach) :
id           └──┘   └───┘  └────┘
src  ─┘      └──┘   └───┘   └────┘
typ  ─┘      └──┘   └───┘  └────┘
doc  ─┘      └──┘   └───┘   └────┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘
1237      card_image_of_injective _ $ assume ⟨i, hi⟩ ⟨j, hj⟩ eq,
id       └─────────────────────┘              └┘    └┘  └┘
src      └─────────────────────┘                            └┘
typ      └─────────────────────┘              └┘    └┘  └┘
1238        subtype.eq $ f_inj i j (mem_range.1 hi) (mem_range.1 hj) eq
id         └────────┘   └───┘      └───────┘       └───────┘      └┘
src        └────────┘              └───────┘       └───────┘      └┘
typ        └────────┘   └───┘      └───────┘       └───────┘      └┘
1239    ... = card (range n) : card_attach
id           └──┘  └───┘     └─────────┘
src          └──┘  └───┘      └─────────┘
typ          └──┘  └───┘     └─────────┘
doc          └──┘  └───┘
1240    ... = n : card_range n
id              └────────┘ 
src              └────────┘
typ             └────────┘ 
1241  
1242  lemma card_eq_succ [decidable_eq α] {s : finset α} {n : ℕ} :
id                       └──────────┘        └────┘        
src                      └──────────┘         └────┘         
typ                      └──────────┘        └────┘        
doc                                           └────┘
1243    s.card = n + 1 ↔ (∃a t, a ∉ t ∧ insert a t = s ∧ card t = n) :=
id     └───┘              └────┘      └──┘   
src     └───┘                   └────┘         └──┘   
typ    └───┘              └────┘      └──┘   
doc     └───┘                                           └──┘
1244  iff.intro
id   └───────┘
src  └───────┘
typ  └───────┘
1245    (assume eq,
id             └┘
src            └┘
typ            └┘
1246      have 0 < card s, from eq.symm ▸ nat.zero_lt_succ _,
id               └──┘        └┘└───┘  └──────────────┘
src              └──┘         └┘└───┘  └──────────────┘
typ              └──┘        └┘└───┘  └──────────────┘
doc               └──┘
1247      let ⟨a, has⟩ := card_pos.mp this in
id       └─┘    └─┘     └──────┘└─┘ └──┘
src                      └──────┘└─┘
typ      └─┘    └─┘     └──────┘└─┘ └──┘
1248      ⟨a, s.erase a, s.not_mem_erase a, insert_erase has, by simp only [eq, card_erase_of_mem has, pred_succ]⟩)
id           └────┘    └────────────┘    └──────────┘                    └┘  └───────────────┘ └─┘  └───────┘
src           └────┘     └────────────┘    └──────────┘         └─────────┘└┘└┘└───────────────┘   └┘└───────┘
typ          └────┘    └────────────┘    └──────────┘         └─────────┘└┘└┘└───────────────┘└─┘└┘└───────┘
doc           └────┘                                            └─────────┘  └┘                    └┘         
txt                                                             └─────────┘  └┘                    └┘         
par                                                             └─────────┘  └┘                    └┘         
pid                                                                 └──┘└┘  └┘                    └┘         
st                                                             └───────────────────────────────────────────────┘
1249    (assume ⟨a, t, hat, s_eq, n_eq⟩, s_eq ▸ n_eq ▸ card_insert_of_not_mem hat)
id                   └─┘  └──┘  └──┘               └────────────────────┘
src                                                 └────────────────────┘
typ                  └─┘  └──┘  └──┘               └────────────────────┘
1250  
1251  theorem card_le_of_subset {s t : finset α} : s ⊆ t → card s ≤ card t :=
id                                    └────┘          └──┘   └──┘ 
src                                   └────┘             └──┘    └──┘
typ                                   └────┘          └──┘   └──┘ 
doc                                   └────┘              └──┘     └──┘
1252  multiset.card_le_of_le ∘ val_le_iff.mpr
id   └────────────────────┘  └────────┘└──┘
src  └────────────────────┘  └────────┘└──┘
typ  └────────────────────┘  └────────┘└──┘
1253  
1254  theorem eq_of_subset_of_card_le {s t : finset α} (h : s ⊆ t) (h₂ : card t ≤ card s) : s = t :=
id                                          └────┘                  └──┘   └──┘       
src                                         └────┘                     └──┘    └──┘        
typ                                         └────┘                  └──┘   └──┘       
doc                                         └────┘                      └──┘     └──┘
1255  eq_of_veq $ multiset.eq_of_le_of_card_le (val_le_iff.mpr h) h₂
id   └───────┘   └──────────────────────────┘  └────────┘└──┘   └┘
src  └───────┘   └──────────────────────────┘  └────────┘└──┘
typ  └───────┘   └──────────────────────────┘  └────────┘└──┘   └┘
1256  
1257  lemma card_lt_card {s t : finset α} (h : s ⊂ t) : s.card < t.card :=
id                             └────┘              └───┘  └───┘
src                            └────┘                  └───┘   └───┘
typ                            └────┘              └───┘  └───┘
doc                            └────┘                   └───┘    └───┘
1258  card_lt_of_lt (val_lt_iff.2 h)
id   └───────────┘  └────────┘  
src  └───────────┘  └────────┘
typ  └───────────┘  └────────┘  
1259  
1260  lemma card_le_card_of_inj_on [decidable_eq β] {s : finset α} {t : finset β}
id                                 └──────────┘        └────┘        └────┘ 
src                                └──────────┘         └────┘         └────┘
typ                                └──────────┘        └────┘        └────┘ 
doc                                                     └────┘         └────┘
1261    (f : α → β) (hf : ∀a∈s, f a ∈ t) (f_inj : ∀a₁∈s, ∀a₂∈s, f a₁ = f a₂ → a₁ = a₂) :
id                                        └┘    └┘    └┘   └┘   └┘  └┘
src                                                                           
typ                                       └┘    └┘    └┘   └┘   └┘  └┘
1262    card s ≤ card t :=
id     └──┘   └──┘ 
src    └──┘    └──┘
typ    └──┘   └──┘ 
doc    └──┘     └──┘
1263  calc card s = card (s.image f) : by rw [card_image_of_inj_on f_inj]
id        └──┘    └──┘  └────┘            └──────────────────┘ └───┘
src       └──┘     └──┘   └────┘         └──┘└──────────────────┘     └─
typ       └──┘    └──┘  └────┘        └──┘└──────────────────┘└───┘└─
doc       └──┘     └──┘   └────┘         └──┘                         └─
txt                                      └──┘                         └─
par                                      └──┘                         └─
pid                                        └┘                         
st                                      └─────────────────────────────┘
1264    ... ≤ card t : card_le_of_subset $
id           └──┘    └───────────────┘
src  ─┘      └──┘     └───────────────┘
typ  ─┘      └──┘    └───────────────┘
doc  ─┘      └──┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘
1265      assume x hx, match x, finset.mem_image.1 hx with _, ⟨a, ha, rfl⟩ := hf a ha end
id               └┘          └──────────────┘  └┘            └┘  └─┘     └┘
src                            └──────────────┘                     └─┘
typ              └┘          └──────────────┘  └┘            └┘  └─┘     └┘
1266  
1267  lemma card_le_of_inj_on [decidable_eq α] {n} {s : finset α}
id                            └──────────┘            └────┘ 
src                           └──────────┘             └────┘
typ                           └──────────┘            └────┘ 
doc                                                    └────┘
1268    (f : ℕ → α) (hf : ∀i<n, f i ∈ s) (f_inj : ∀i j, i<n → j<n → f i = f j → i = j) : n ≤ card s :=
id                                                                └──┘ 
src                                                                                 └──┘
typ                                                               └──┘ 
doc                                                                                         └──┘
1269  calc n = card (range n) : (card_range n).symm
id           └──┘  └───┘      └────────┘  └──┘
src           └──┘  └───┘       └────────┘   └──┘
typ          └──┘  └───┘      └────────┘  └──┘
doc           └──┘  └───┘
1270    ... ≤ card s : card_le_card_of_inj_on f
id           └──┘    └────────────────────┘ 
src          └──┘     └────────────────────┘
typ          └──┘    └────────────────────┘ 
doc          └──┘
1271      (by simpa only [mem_range])
id                       └───────┘
src          └──────────┘└───────┘
typ          └──────────┘└───────┘
doc          └──────────┘         
txt          └──────────┘         
par          └──────────┘         
pid               └──┘└┘         
st          └─────────────────────┘
1272      (by simp only [mem_range]; exact assume a₁ h₁ a₂ h₂, f_inj a₁ a₂ h₁ h₂)
id                      └───────┘                             └───┘
src          └─────────┘└───────┘  └────┘      └────────────┘           
typ          └─────────┘└───────┘  └────┘      └────────────┘└───┘      
doc          └─────────┘           └────┘      └────────────┘           
txt          └─────────┘           └────┘      └────────────┘           
par          └─────────┘           └────┘      └────────────┘           
pid              └──┘└┘                      └────────────┘           
st          └─────────────────────────────────────────────────────────────────┘
1273  
1274  @[elab_as_eliminator] def strong_induction_on {p : finset α → Sort*} :
id                                                      └────┘ 
src                                                     └────┘
typ                                                     └────┘ 
doc    └────────────────┘                               └────┘
1275    ∀ (s : finset α), (∀s, (∀t ⊂ s, p t) → p s) → p s
id           └────┘                          
src           └────┘            
typ          └────┘                          
doc           └────┘
1276  | ⟨s, nd⟩ ih := multiset.strong_induction_on s
id        └┘  └┘    └──────────────────────────┘
src                  └──────────────────────────┘
typ       └┘  └┘    └──────────────────────────┘
1277    (λ s IH nd, ih ⟨s, nd⟩ (λ ⟨t, nd'⟩ ss, IH t (val_lt_iff.2 ss) nd')) nd
id         └┘ └┘        └┘       └─┘  └┘  └┘    └────────┘  └┘
src                                                 └────────┘
typ        └┘ └┘        └┘       └─┘  └┘  └┘    └────────┘  └┘
1278  
1279  @[elab_as_eliminator] lemma case_strong_induction_on [decidable_eq α] {p : finset α → Prop}
id                                                         └──────────┘        └────┘ 
src                                                        └──────────┘         └────┘
typ                                                        └──────────┘        └────┘ 
doc    └────────────────┘                                                       └────┘
1280    (s : finset α) (h₀ : p ∅) (h₁ : ∀ a s, a ∉ s → (∀t ⊆ s, p t) → p (insert a s)) : p s :=
id          └────┘                                          └────┘        
src         └────┘                                                    └────┘
typ         └────┘                                          └────┘        
doc         └────┘
1281  finset.strong_induction_on s $ λ s,
id   └────────────────────────┘      
src  └────────────────────────┘
typ  └────────────────────────┘      
1282  finset.induction_on s (λ _, h₀) $ λ a s n _ ih, h₁ a s n $
id   └─────────────────┘       └┘          └┘  └┘   
src  └─────────────────┘
typ  └─────────────────┘       └┘          └┘  └┘   
doc  └─────────────────┘
1283  λ t ss, ih _ (lt_of_le_of_lt ss (ssubset_insert n) : t < _)
id      └┘  └┘    └────────────┘ └┘  └────────────┘      
src                └────────────┘     └────────────┘        
typ     └┘  └┘    └────────────┘ └┘  └────────────┘      
1284  
1285  lemma card_congr {s : finset α} {t : finset β} (f : Π a ∈ s, β)
id                         └────┘        └────┘               
src                        └────┘         └────┘
typ                        └────┘        └────┘               
doc                        └────┘         └────┘
1286    (h₁ : ∀ a ha, f a ha ∈ t) (h₂ : ∀ a b ha hb, f a ha = f b hb → a = b)
id              └┘    └┘              └┘ └┘    └┘    └┘     
src                                                                   
typ             └┘    └┘              └┘ └┘    └┘    └┘     
1287    (h₃ : ∀ b ∈ t, ∃ a ha, f a ha = b) : s.card = t.card :=
id                    └┘   └┘      └───┘  └───┘
src                                       └───┘   └───┘
typ                   └┘   └┘      └───┘  └───┘
doc                                          └───┘    └───┘
1288  by haveI := classical.prop_decidable; exact
id               └──────────────────────┘
src     └───────┘└──────────────────────┘  └────┘
typ     └───────┘└──────────────────────┘  └────┘
doc     └───────┘                          └────┘
txt     └───────┘                          └────┘
par     └───────┘                          └────┘
pid          └─┘                               
st     └─────────────────────────────────────────
1289  calc s.card = s.attach.card : card_attach.symm
id        └────┘   └───────────┘   └──────────────┘
src      └────┘ └───────────┘└─┘└──────────────┘
typ      └────┘ └───────────┘└─┘└──────────────┘
doc      └────┘ └───────────┘└─┘                
txt                          └─┘                
par                          └─┘                
pid                          └─┘                
st   ───────────────────────────────────────────────
1290  ... = (s.attach.image (λ (a : {a // a ∈ s}), f a.1 a.2)).card :
id          └────────────┘                      
src  ───┘  └────────────┘  └────┘└───┘  └──┘  └─┘ └───────────
typ  ───┘  └────────────┘  └────┘└───┘  └──┘ └─┘ └───────────
doc  ───┘  └────────────┘  └────┘ └───┘   └──┘  └─┘ └───────────
txt  ───┘                  └────┘ └───┘   └──┘  └─┘ └───────────
par  ───┘                  └────┘ └───┘   └──┘  └─┘ └───────────
pid  ───┘                  └────┘ └───┘   └──┘  └─┘ └───────────
st   ────────────────────────────────────────────────────────────────
1291    eq.symm (card_image_of_injective _ (λ a b h, subtype.eq (h₂ _ _ _ _ h)))
id     └─────┘  └─────────────────────┘             └────────┘  └┘
src  ─┘└─────┘ └─────────────────────┘└─┘  └──────┘└────────┘   └───────┘ └───
typ  ─┘└─────┘ └─────────────────────┘└─┘  └──────┘└────────┘ └┘└───────┘ └───
doc  ─┘                               └─┘  └──────┘             └───────┘ └───
txt  ─┘                               └─┘  └──────┘             └───────┘ └───
par  ─┘                               └─┘  └──────┘             └───────┘ └───
pid  ─┘                               └─┘  └──────┘             └───────┘ └───
st   ───────────────────────────────────────────────────────────────────────────
1292  ... = t.card : congr_arg card (finset.ext.2 $ λ b,
id         └────┘   └───────┘ └──┘  └────────┘
src  ───┘ └────┘└─┘└───────┘└──┘ └────────┘└─┘  └───
typ  ───┘ └────┘└─┘└───────┘└──┘ └────────┘└─┘  └───
doc  ───┘ └────┘└─┘         └──┘           └─┘  └───
txt  ───┘       └─┘                        └─┘  └───
par  ───┘       └─┘                        └─┘  └───
pid  ───┘       └─┘                        └─┘  └───
st   ───────────────────────────────────────────────────
1293      ⟨λ h, let ⟨a, ha₁, ha₂⟩ := mem_image.1 h in ha₂ ▸ h₁ _ _,
id                          └─┘                           └┘
src  ───┘  └──┘     └┘   └┘   └───┘         └─┘ └──┘     └─────
typ  ───┘  └──┘     └┘   └┘└─┘└───┘         └─┘ └──┘   └┘└─────
doc  ───┘  └──┘     └┘   └┘   └───┘         └─┘ └──┘      └─────
txt  ───┘  └──┘     └┘   └┘   └───┘         └─┘ └──┘      └─────
par  ───┘  └──┘     └┘   └┘   └───┘         └─┘ └──┘      └─────
pid  ───┘  └──┘     └┘   └┘   └───┘         └─┘ └──┘      └─────
st   ──────────────────────────────────────────────────────────────
1294        λ h, let ⟨a, ha₁, ha₂⟩ := h₃ b h in mem_image.2 ⟨⟨a, ha₁⟩, by simp [ha₂]⟩⟩)
id                     └─┘          └┘        └───────┘                       └─┘
src  ─────┘ └──┘     └┘   └┘   └───┘    └──┘└───────┘└─┘   └┘   └─┘  └────┘   └───
typ  ─────┘ └──┘    └┘└─┘└┘   └───┘└┘  └──┘└───────┘└─┘   └┘   └─┘  └────┘└─┘└───
doc  ─────┘ └──┘     └┘   └┘   └───┘    └──┘         └─┘   └┘   └─┘  └────┘   └───
txt  ─────┘ └──┘     └┘   └┘   └───┘    └──┘         └─┘   └┘   └─┘  └────┘   └───
par  ─────┘ └──┘     └┘   └┘   └───┘    └──┘         └─┘   └┘   └─┘  └────┘   └───
pid  ─────┘ └──┘     └┘   └┘   └───┘    └──┘         └─┘   └┘   └─┘  └─────┘   └──┘
st   ──────────────────────────────────────────────────────────────────┘└─────────┘└───
1295  
src  
typ  
doc  
txt  
par  
pid  
st   
1296  lemma card_union_add_card_inter [decidable_eq α] (s t : finset α) :
id                                    └──────────┘          └────┘ 
src                                   └──────────┘           └────┘
typ                                   └──────────┘          └────┘ 
doc                                                          └────┘
1297    (s ∪ t).card + (s ∩ t).card = s.card + t.card :=
id         └──┘       └──┘   └───┘  └───┘
src          └──┘         └──┘    └───┘   └───┘
typ        └──┘       └──┘   └───┘  └───┘
doc           └──┘           └──┘     └───┘    └───┘
1298  finset.induction_on t (by simp) (λ a, by by_cases a ∈ s; simp * {contextual := tt})
id   └─────────────────┘                                                       └┘
src  └─────────────────┘       └──┘           └───────┘    └─────┘ └────────────┘└┘
typ  └─────────────────┘      └──┘          └───────┘  └─────┘ └────────────┘└┘
doc  └─────────────────┘       └──┘           └───────┘     └─────┘ └────────────┘  
txt                            └──┘           └───────┘     └─────┘ └────────────┘  
par                            └──┘           └───────┘     └─────┘ └────────────┘  
pid                                                             └────────────┘  
st                            └───┘          └────────────────────────────────────────┘
1299  
1300  lemma card_union_le [decidable_eq α] (s t : finset α) :
id                        └──────────┘          └────┘ 
src                       └──────────┘           └────┘
typ                       └──────────┘          └────┘ 
doc                                              └────┘
1301    (s ∪ t).card ≤ s.card + t.card :=
id         └──┘   └───┘  └───┘
src          └──┘    └───┘   └───┘
typ        └──┘   └───┘  └───┘
doc           └──┘     └───┘    └───┘
1302  card_union_add_card_inter s t ▸ le_add_right _ _
id   └───────────────────────┘    └──────────┘
src  └───────────────────────┘      └──────────┘
typ  └───────────────────────┘    └──────────┘
1303  
1304  lemma surj_on_of_inj_on_of_card_le {s : finset α} {t : finset β}
id                                           └────┘        └────┘ 
src                                          └────┘         └────┘
typ                                          └────┘        └────┘ 
doc                                          └────┘         └────┘
1305    (f : Π a ∈ s, β) (hf : ∀ a ha, f a ha ∈ t)
id                            └┘    └┘  
src                                          
typ                           └┘    └┘  
1306    (hinj : ∀ a₁ a₂ ha₁ ha₂, f a₁ ha₁ = f a₂ ha₂ → a₁ = a₂)
id               └┘ └┘ └─┘ └─┘   └┘ └─┘   └┘ └─┘   └┘  └┘
src                                                     
typ              └┘ └┘ └─┘ └─┘   └┘ └─┘   └┘ └─┘   └┘  └┘
1307    (hst : card t ≤ card s) :
id            └──┘   └──┘ 
src           └──┘    └──┘
typ           └──┘   └──┘ 
doc           └──┘     └──┘
1308    (∀ b ∈ t, ∃ a ha, b = f a ha) :=
id               └┘     └┘
src                      
typ              └┘     └┘
1309  by haveI := classical.dec_eq β; exact
id               └──────────────┘ 
src     └───────┘└──────────────┘   └────┘
typ     └───────┘└──────────────┘  └────┘
doc     └───────┘                   └────┘
txt     └───────┘                   └────┘
par     └───────┘                   └────┘
pid          └─┘                        
st     └───────────────────────────────────
1310  λ b hb,
src   └──────
typ   └──────
doc   └──────
txt   └──────
par   └──────
pid   └──────
st   ────────
1311    have h : card (image (λ (a : {a // a ∈ s}), f (a.val) a.2) (attach s)) = card s,
id                                                   └──┘        └────┘      └──┘
src  ─┘    └───┘            └────┘└───┘  └──┘   └──┘└┘ └──┘ └────┘ └─┘└──┘ └─
typ  ─┘    └───┘            └────┘└───┘  └──┘   └──┘└┘ └──┘ └────┘ └─┘└──┘ └─
doc  ─┘    └───┘            └────┘ └───┘   └──┘       └┘ └──┘ └────┘ └─┘ └──┘ └─
txt  ─┘    └───┘            └────┘ └───┘   └──┘       └┘ └──┘        └─┘      └─
par  ─┘    └───┘            └────┘ └───┘   └──┘       └┘ └──┘        └─┘      └─
pid  ─┘    └───┘            └────┘ └───┘   └──┘       └┘ └──┘        └─┘      └─
st   ───────────────────────────────────────────────────────────────────────────────────
1312      from @card_attach _ s ▸ card_image_of_injective _
id             └─────────┘      └─────────────────────┘
src  ────────┘ └─────────┘└─┘  └─────────────────────┘└──
typ  ────────┘ └─────────┘└─┘ └─────────────────────┘└──
doc  ────────┘            └─┘                         └──
txt  ────────┘            └─┘                         └──
par  ────────┘            └─┘                         └──
pid  ────────┘            └─┘                         └──
st   ──────────────────────────────────────────────────────
1313        (λ ⟨a₁, ha₁⟩ ⟨a₂, ha₂⟩ h, subtype.eq $ hinj _ _ _ _ h),
id                                   └────────┘   └──┘
src  ─────┘  └┘  └┘   └─┘  └┘   └───┘└────────┘     └───────┘ └──
typ  ─────┘  └┘  └┘   └─┘  └┘   └───┘└────────┘ └──┘└───────┘ └──
doc  ─────┘  └┘  └┘   └─┘  └┘   └───┘               └───────┘ └──
txt  ─────┘  └┘  └┘   └─┘  └┘   └───┘               └───────┘ └──
par  ─────┘  └┘  └┘   └─┘  └┘   └───┘               └───────┘ └──
pid  ─────┘  └┘  └┘   └─┘  └┘   └───┘               └───────┘ └──
st   ──────────────────────────────────────────────────────────────
1314    have h₁ : image (λ a : {a // a ∈ s}, f a.1 a.2) s.attach = t :=
id               └───┘                               └──────┘   
src  ─┘    └────┘└───┘  └───┘ └───┘   └─┘  └─┘ └──┘└──────┘  └───
typ  ─┘    └────┘└───┘  └───┘└───┘   └─┘ └─┘ └──┘└──────┘ └───
doc  ─┘    └────┘└───┘  └───┘ └───┘   └─┘  └─┘ └──┘└──────┘  └───
txt  ─┘    └────┘       └───┘ └───┘   └─┘  └─┘ └──┘          └───
par  ─┘    └────┘       └───┘ └───┘   └─┘  └─┘ └──┘          └───
pid  ─┘    └────┘       └───┘ └───┘   └─┘  └─┘ └──┘          └───
st   ──────────────────────────────────────────────────────────────────
1315    eq_of_subset_of_card_le (λ b h, let ⟨a, ha₁, ha₂⟩ := mem_image.1 h in
id     └─────────────────────┘                      └─┘     └───────┘
src  ─┘└─────────────────────┘  └────┘     └┘   └┘   └───┘└───────┘└─┘ └───
typ  ─┘└─────────────────────┘  └────┘     └┘   └┘└─┘└───┘└───────┘└─┘ └───
doc  ─┘                         └────┘     └┘   └┘   └───┘         └─┘ └───
txt  ─┘                         └────┘     └┘   └┘   └───┘         └─┘ └───
par  ─┘                         └────┘     └┘   └┘   └───┘         └─┘ └───
pid  ─┘                         └────┘     └┘   └┘   └───┘         └─┘ └───
st   ────────────────────────────────────────────────────────────────────────
1316      ha₂ ▸ hf _ _) (by simp [hst, h]),
id            └┘                └─┘  
src  ───┘     └────┘   └────┘   └┘ └─┘
typ  ───┘   └┘└────┘   └────┘└─┘└┘└─┘
doc  ───┘      └────┘   └────┘   └┘ └─┘
txt  ───┘      └────┘   └────┘   └┘ └─┘
par  ───┘      └────┘   └────┘   └┘ └─┘
pid  ───┘      └────┘   └─────┘   └┘ └──┘
st   ────────────────────┘└────────────┘└─┘
1317  begin
src       
typ       
doc       
txt       
par       
pid       
st   └─────
1318    rw ← h₁ at hb,
id          └┘
src  ─┘└───┘  └────┘└─
typ  ─┘└───┘└┘└────┘└─
doc  ─┘└───┘  └────┘└─
txt  ─┘└───┘  └────┘└─
par  ─┘└───┘  └────┘└─
pid  ──────┘  └───────
st   ──────────────┘└─
1319    rcases mem_image.1 hb with ⟨a, ha₁, ha₂⟩,
id            └───────┘   └┘
src  ─┘└─────┘└───────┘└─┘  └─────────────────┘└─
typ  ─┘└─────┘└───────┘└─┘└┘└─────────────────┘└─
doc  ─┘└─────┘         └─┘  └─────────────────┘└─
txt  ─┘└─────┘         └─┘  └─────────────────┘└─
par  ─┘└─────┘         └─┘  └─────────────────┘└─
pid  ────────┘         └─┘  └────────────────────
st   ─────────────────────────────────────────┘└─
1320    exact ⟨a, a.2, ha₂.symm⟩,
id                   └──────┘
src  ───────┘  └┘ └──┘└──────┘└──
typ  ───────┘  └┘└──┘└──────┘└──
doc  ───────┘  └┘ └──┘        └──
txt  ───────┘  └┘ └──┘        └──
par  ───────┘  └┘ └──┘        └──
pid  ───────┘  └┘ └──┘        └──
st   ─────────────────────────┘└─
1321  end
src  ────
typ  ────
doc  ────
txt  ────
par  ────
pid  ──┘
st   ──┘
1322  
src  
typ  
doc  
txt  
par  
pid  
st   
1323  open function
1324  
1325  lemma inj_on_of_surj_on_of_card_le {s : finset α} {t : finset β}
id                                           └────┘        └────┘ 
src                                          └────┘         └────┘
typ                                          └────┘        └────┘ 
doc                                          └────┘         └────┘
1326    (f : Π a ∈ s, β) (hf : ∀ a ha, f a ha ∈ t)
id                            └┘    └┘  
src                                          
typ                           └┘    └┘  
1327    (hsurj : ∀ b ∈ t, ∃ a ha, b = f a ha)
id                       └┘     └┘
src                              
typ                      └┘     └┘
1328    (hst : card s ≤ card t)
id            └──┘   └──┘ 
src           └──┘    └──┘
typ           └──┘   └──┘ 
doc           └──┘     └──┘
1329    ⦃a₁ a₂⦄ (ha₁ : a₁ ∈ s) (ha₂ : a₂ ∈ s)
id                    └┘           └┘  
src                                    
typ                   └┘           └┘  
1330    (ha₁a₂: f a₁ ha₁ = f a₂ ha₂) : a₁ = a₂ :=
id              └┘ └─┘   └┘ └─┘    └┘  └┘
src                                     
typ             └┘ └─┘   └┘ └─┘    └┘  └┘
1331  by haveI : inhabited {x // x ∈ s} := ⟨⟨a₁, ha₁⟩⟩; exact
id              └───────┘                └┘  └─┘
src     └──────┘└───────┘└───┘  └───┘    └┘   └┘  └────┘
typ     └──────┘└───────┘└───┘ └───┘  └┘└┘└─┘└┘  └────┘
doc     └──────┘          └───┘   └───┘    └┘   └┘  └────┘
txt     └──────┘          └───┘   └───┘    └┘   └┘  └────┘
par     └──────┘          └───┘   └───┘    └┘   └┘  └────┘
pid          └┘          └───┘   └──┘    └┘   └┘       
st     └─────────────────────────────────────────────────────
1332  let f' : {x // x ∈ s} → {x // x ∈ t} := λ x, ⟨f x.1 x.2, hf x.1 x.2⟩ in
id                                                         └┘
src     └────┘ └───┘   └┘  └───┘   └───┘ └──┘   └─┘ └──┘   └─┘ └─────┘
typ     └────┘└───┘   └┘ └───┘   └───┘ └──┘  └─┘ └──┘└┘ └─┘ └─────┘
doc     └────┘ └───┘   └┘  └───┘   └───┘ └──┘   └─┘ └──┘   └─┘ └─────┘
txt     └────┘ └───┘   └┘  └───┘   └───┘ └──┘   └─┘ └──┘   └─┘ └─────┘
par     └────┘ └───┘   └┘  └───┘   └───┘ └──┘   └─┘ └──┘   └─┘ └─────┘
pid     └────┘ └───┘   └┘  └───┘   └───┘ └──┘   └─┘ └──┘   └─┘ └─────┘
st   ────────────────────────────────────────────────────────────────────────
1333  let g : {x // x ∈ t} → {x // x ∈ s} :=
id                       
src     └───┘ └───┘   └┘  └───┘   └────
typ     └───┘└───┘   └┘ └───┘   └────
doc     └───┘ └───┘   └┘  └───┘   └────
txt     └───┘ └───┘   └┘  └───┘   └────
par     └───┘ └───┘   └┘  └───┘   └────
pid     └───┘ └───┘   └┘  └───┘   └────
st   ───────────────────────────────────────
1334    @surj_inv _ _ f'
id      └──────┘
src  ─┘ └──────┘└───┘  
typ  ─┘ └──────┘└───┘  
doc  ─┘ └──────┘└───┘  
txt  ─┘         └───┘  
par  ─┘         └───┘  
pid  ─┘         └───┘  
st   ───────────────────
1335      (λ x, let ⟨y, hy₁, hy₂⟩ := hsurj x.1 x.2 in ⟨⟨y, hy₁⟩, subtype.eq hy₂.symm⟩) in
id                    └─┘  └─┘     └───┘                                     └───┘
src  ───┘  └──┘     └┘   └┘   └───┘      └─┘ └────┘   └┘   └─┘             └───┘└────┘
typ  ───┘  └──┘    └┘└─┘└┘└─┘└───┘└───┘ └─┘ └────┘   └┘   └─┘             └───┘└────┘
doc  ───┘  └──┘     └┘   └┘   └───┘      └─┘ └────┘   └┘   └─┘                  └────┘
txt  ───┘  └──┘     └┘   └┘   └───┘      └─┘ └────┘   └┘   └─┘                  └────┘
par  ───┘  └──┘     └┘   └┘   └───┘      └─┘ └────┘   └┘   └─┘                  └────┘
pid  ───┘  └──┘     └┘   └┘   └───┘      └─┘ └────┘   └┘   └─┘                  └────┘
st   ────────────────────────────────────────────────────────────────────────────────────
1336  have hg : injective g, from function.injective_surj_inv _,
id                               └─────────────────────────┘
src      └────┘          └─────┘└─────────────────────────┘└──┘
typ      └────┘          └─────┘└─────────────────────────┘└──┘
doc      └────┘          └─────┘                           └──┘
txt      └────┘          └─────┘                           └──┘
par      └────┘          └─────┘                           └──┘
pid      └────┘          └─────┘                           └──┘
st   ───────────────────────────────────────────────────────────
1337  have hsg : surjective g, from λ x,
id              └────────┘
src      └─────┘└────────┘ └─────┘ └───
typ      └─────┘└────────┘ └─────┘ └───
doc      └─────┘           └─────┘ └───
txt      └─────┘           └─────┘ └───
par      └─────┘           └─────┘ └───
pid      └─────┘           └─────┘ └───
st   ───────────────────────────────────
1338    let ⟨y, hy⟩ := surj_on_of_inj_on_of_card_le (λ (x : {x // x ∈ t}) (hx : x ∈ t.attach), g x)
id            └┘     └──────────────────────────┘                               └──────┘
src  ─┘     └┘  └───┘└──────────────────────────┘  └────┘ └───┘   └───────┘  └──────┘└─┘  └─
typ  ─┘    └┘└┘└───┘└──────────────────────────┘  └────┘└───┘   └───────┘ └──────┘└─┘  └─
doc  ─┘     └┘  └───┘                              └────┘ └───┘   └───────┘  └──────┘└─┘  └─
txt  ─┘     └┘  └───┘                              └────┘ └───┘   └───────┘          └─┘  └─
par  ─┘     └┘  └───┘                              └────┘ └───┘   └───────┘          └─┘  └─
pid  ─┘     └┘  └───┘                              └────┘ └───┘   └───────┘          └─┘  └─
st   ──────────────────────────────────────────────────────────────────────────────────────────────
1339      (λ x _, show (g x) ∈ s.attach, from mem_attach _ _)
id                           └──────┘
src  ───┘  └────┘       └┘ └──────┘└─────┘          └─────
typ  ───┘  └────┘       └┘└──────┘└─────┘          └─────
doc  ───┘  └────┘       └┘ └──────┘└─────┘          └─────
txt  ───┘  └────┘       └┘         └─────┘          └─────
par  ───┘  └────┘       └┘         └─────┘          └─────
pid  ───┘  └────┘       └┘         └─────┘          └─────
st   ────────────────────────────────────────────────────────
1340      (λ x y _ _ hxy, hg hxy) (by simpa) x (mem_attach _ _) in
id                                             └────────┘
src  ───┘  └────────────┘     └┘   └───┘└┘  └────────┘└────────
typ  ───┘  └────────────┘     └┘   └───┘└┘  └────────┘└────────
doc  ───┘  └────────────┘     └┘   └───┘└┘            └────────
txt  ───┘  └────────────┘     └┘   └───┘└┘            └────────
par  ───┘  └────────────┘     └┘   └───┘└┘            └────────
pid  ───┘  └────────────┘     └┘   └──────┘            └────────
st   ──────────────────────────────┘└────┘└───────────────────────
1341    ⟨y, hy.snd.symm⟩,
id           └──┘└───┘
src  ─┘  └┘  └──┘└───┘└─┘
typ  ─┘  └┘  └──┘└───┘└─┘
doc  ─┘  └┘           └─┘
txt  ─┘  └┘           └─┘
par  ─┘  └┘           └─┘
pid  ─┘  └┘           └─┘
st   ────────────────────
1342  have hif : injective f',
id              └───────┘
src      └─────┘└───────┘  └─
typ      └─────┘└───────┘  └─
doc      └─────┘           └─
txt      └─────┘           └─
par      └─────┘           └─
pid      └─────┘           └─
st   ─────────────────────────
1343    from injective_of_has_left_inverse
id          └───────────────────────────┘
src  ──────┘└───────────────────────────┘
typ  ──────┘└───────────────────────────┘
doc  ──────┘                             
txt  ──────┘                             
par  ──────┘                             
pid  ──────┘                             
st   ─────────────────────────────────────
1344      ⟨g, left_inverse_of_surjective_of_right_inverse hsg
id           └─────────────────────────────────────────┘
src  ───┘  └┘└─────────────────────────────────────────┘   
typ  ───┘  └┘└─────────────────────────────────────────┘   
doc  ───┘  └┘                                              
txt  ───┘  └┘                                              
par  ───┘  └┘                                              
pid  ───┘  └┘                                              
st   ────────────────────────────────────────────────────────
1345        (right_inverse_surj_inv _)⟩,
id          └────────────────────┘
src  ─────┘ └────────────────────┘└────┘
typ  ─────┘ └────────────────────┘└────┘
doc  ─────┘                       └────┘
txt  ─────┘                       └────┘
par  ─────┘                       └────┘
pid  ─────┘                       └────┘
st   ───────────────────────────────────
1346  subtype.ext.1 (@hif ⟨a₁, ha₁⟩ ⟨a₂, ha₂⟩ (subtype.eq ha₁a₂))
id   └─────────┘          └┘  └─┘   └┘  └─┘   └────────┘ └───┘
src  └─────────┘└─┘        └┘   └┘   └┘   └┘ └────────┘     └──
typ  └─────────┘└─┘      └┘└┘└─┘└┘ └┘└┘└─┘└┘ └────────┘└───┘└──
doc             └─┘        └┘   └┘   └┘   └┘                └──
txt             └─┘        └┘   └┘   └┘   └┘                └──
par             └─┘        └┘   └┘   └┘   └┘                └──
pid             └─┘        └┘   └┘   └┘   └┘                └┘
st   ────────────────────────────────────────────────────────────
1347  
src  
typ  
doc  
txt  
par  
pid  
st   
1348  end card
1349  
1350  /-! ### bind -/
1351  section bind
1352  variables [decidable_eq β] {s : finset α} {t : α → finset β}
id              └──────────┘         └────┘             └────┘
src             └──────────┘         └────┘             └────┘
typ             └──────────┘         └────┘             └────┘
doc                                  └────┘             └────┘
1353  
1354  /-- `bind s t` is the union of `t x` over `x ∈ s` -/
1355  protected def bind (s : finset α) (t : α → finset β) : finset β := (s.1.bind (λ a, (t a).1)).to_finset
id                           └────┘           └────┘     └────┘       └──┘             └───────┘
src                          └────┘             └────┘      └────┘         └──┘                └───────┘
typ                          └────┘           └────┘     └────┘       └──┘             └───────┘
doc                          └────┘             └────┘      └────┘          └──┘                 └───────┘
1356  
1357  @[simp] theorem bind_val (s : finset α) (t : α → finset β) :
id                                 └────┘           └────┘ 
src                                └────┘             └────┘
typ                                └────┘           └────┘ 
doc    └──┘                        └────┘             └────┘
1358    (s.bind t).1 = (s.1.bind (λ a, (t a).1)).erase_dup := rfl
id      └───┘       └──┘             └───────┘     └─┘
src      └───┘         └──┘                └───────┘     └─┘
typ     └───┘       └──┘             └───────┘     └─┘
doc      └───┘            └──┘                 └───────┘
1359  
1360  @[simp] theorem bind_empty : finset.bind ∅ t = ∅ := rfl
id                                └─────────┘        └─┘
src                               └─────────┘         └─┘
typ                               └─────────┘        └─┘
doc    └──┘                       └─────────┘
1361  
1362  @[simp] theorem mem_bind {b : β} : b ∈ s.bind t ↔ ∃a∈s, b ∈ t a :=
id                                       └───┘        
src                                         └───┘          
typ                                      └───┘        
doc    └──┘                                  └───┘
1363  by simp only [mem_def, bind_val, mem_erase_dup, mem_bind, exists_prop]
id                 └─────┘  └──────┘  └───────────┘  └──────┘  └─────────┘
src     └─────────┘└─────┘└┘└──────┘└┘└───────────┘└┘└──────┘└┘└─────────┘└─
typ     └─────────┘└─────┘└┘└──────┘└┘└───────────┘└┘└──────┘└┘└─────────┘└─
doc     └─────────┘       └┘        └┘             └┘        └┘           └─
txt     └─────────┘       └┘        └┘             └┘        └┘           └─
par     └─────────┘       └┘        └┘             └┘        └┘           └─
pid         └──┘└┘       └┘        └┘             └┘        └┘           
st     └────────────────────────────────────────────────────────────────────
1364  
src  
typ  
doc  
txt  
par  
pid  
st   
1365  @[simp] theorem bind_insert [decidable_eq α] {a : α} : (insert a s).bind t = t a ∪ s.bind t :=
id                                └──────────┘             └────┘   └──┘       └───┘ 
src                               └──────────┘               └────┘     └──┘           └───┘
typ                               └──────────┘             └────┘   └──┘       └───┘ 
doc    └──┘                                                             └──┘             └───┘
1366  ext.2 $ λ x, by simp only [mem_bind, exists_prop, mem_union, mem_insert,
id   └─┘                      └──────┘  └─────────┘  └───────┘  └────────┘
src  └─┘            └─────────┘└──────┘└┘└─────────┘└┘└───────┘└┘└────────┘└─
typ  └─┘           └─────────┘└──────┘└┘└─────────┘└┘└───────┘└┘└────────┘└─
doc                  └─────────┘        └┘           └┘         └┘          └─
txt                  └─────────┘        └┘           └┘         └┘          └─
par                  └─────────┘        └┘           └┘         └┘          └─
pid                      └──┘└┘        └┘           └┘         └┘          └─
st                  └─────────────────────────────────────────────────────────
1367    or_and_distrib_right, exists_or_distrib, exists_eq_left]
id     └──────────────────┘  └───────────────┘  └────────────┘
src  ─┘└──────────────────┘└┘└───────────────┘└┘└────────────┘└─
typ  ─┘└──────────────────┘└┘└───────────────┘└┘└────────────┘└─
doc  ─┘                    └┘                 └┘              └─
txt  ─┘                    └┘                 └┘              └─
par  ─┘                    └┘                 └┘              └─
pid  ─┘                    └┘                 └┘              
st   ───────────────────────────────────────────────────────────
1368  -- ext.2 $ λ x, by simp [or_and_distrib_right, exists_or_distrib]
src  ──────────────────────────────────────────────────────────────────
typ  ──────────────────────────────────────────────────────────────────
doc  ──────────────────────────────────────────────────────────────────
txt  ──────────────────────────────────────────────────────────────────
par  ──────────────────────────────────────────────────────────────────
pid  ──────────────────────────────────────────────────────────────────
st   ──────────────────────────────────────────────────────────────────
1369  
src  
typ  
doc  
txt  
par  
pid  
st   
1370  @[simp] lemma singleton_bind [decidable_eq α] {a : α} : (singleton a).bind t = t a :=
id                                 └──────────┘             └───────┘  └──┘     
src                                └──────────┘               └───────┘   └──┘    
typ                                └──────────┘             └───────┘  └──┘     
doc    └──┘                                                   └───────┘   └──┘
1371  show (insert a ∅ : finset α).bind t = t a, from bind_insert.trans $ union_empty _
id         └────┘     └────┘  └──┘            └─────────┘└────┘   └─────────┘
src        └────┘      └────┘   └──┘               └─────────┘└────┘   └─────────┘
typ        └────┘     └────┘  └──┘            └─────────┘└────┘   └─────────┘
doc                     └────┘   └──┘
1372  
1373  theorem bind_inter (s : finset α) (f : α → finset β) (t : finset β) :
id                           └────┘           └────┘        └────┘ 
src                          └────┘             └────┘         └────┘
typ                          └────┘           └────┘        └────┘ 
doc                          └────┘             └────┘         └────┘
1374    s.bind f ∩ t = s.bind (λ x, f x ∩ t) :=
id     └───┘     └───┘         
src     └───┘        └───┘           
typ    └───┘     └───┘         
doc     └───┘          └───┘
1375  by { ext x, simp, exact ⟨λ ⟨xt, y, ys, xf⟩, ⟨y, ys, xt, xf⟩, λ ⟨y, ys, xt, xf⟩, ⟨xt, y, ys, xf⟩⟩ }
id                               └┘    └┘  └┘                         └┘  └┘  └┘
src       └───┘  └──┘  └────┘  └┘  └┘ └┘  └┘  └─┘  └┘  └┘  └┘  └─┘ └┘ └┘  └┘  └┘  └─┘   └┘ └┘  └┘  └─┘
typ       └───┘  └──┘  └────┘  └┘└┘└┘└┘└┘└┘└┘└─┘  └┘  └┘  └┘  └─┘ └┘└┘└┘└┘└┘└┘└┘└─┘   └┘ └┘  └┘  └─┘
doc       └───┘  └──┘  └────┘  └┘  └┘ └┘  └┘  └─┘  └┘  └┘  └┘  └─┘ └┘ └┘  └┘  └┘  └─┘   └┘ └┘  └┘  └─┘
txt       └───┘  └──┘  └────┘  └┘  └┘ └┘  └┘  └─┘  └┘  └┘  └┘  └─┘ └┘ └┘  └┘  └┘  └─┘   └┘ └┘  └┘  └─┘
par       └───┘  └──┘  └────┘  └┘  └┘ └┘  └┘  └─┘  └┘  └┘  └┘  └─┘ └┘ └┘  └┘  └┘  └─┘   └┘ └┘  └┘  └─┘
pid          └┘               └┘  └┘ └┘  └┘  └─┘  └┘  └┘  └┘  └─┘ └┘ └┘  └┘  └┘  └─┘   └┘ └┘  └┘  └┘
st     └──────┘└────┘└───────────────────────────────────────────────────────────────────────────────┘└┘
1376  
1377  theorem inter_bind (t : finset β) (s : finset α) (f : α → finset β) :
id                           └────┘        └────┘           └────┘ 
src                          └────┘         └────┘             └────┘
typ                          └────┘        └────┘           └────┘ 
doc                          └────┘         └────┘             └────┘
1378    t ∩ s.bind f = s.bind (λ x, t ∩ f x) :=
id       └───┘   └───┘         
src        └───┘     └───┘         
typ      └───┘   └───┘         
doc         └───┘      └───┘
1379  by rw [inter_comm, bind_inter]; simp
id          └────────┘  └────────┘
src     └──┘└────────┘└┘└────────┘  └────
typ     └──┘└────────┘└┘└────────┘  └────
doc     └──┘          └┘            └────
txt     └──┘          └┘            └────
par     └──┘          └┘            └────
pid       └┘          └┘                
st     └─────────────┘└──────────┘└──────
1380  
src  
typ  
doc  
txt  
par  
pid  
st   
1381  theorem image_bind [decidable_eq γ] {f : α → β} {s : finset α} {t : β → finset γ} :
id                       └──────────┘                  └────┘           └────┘ 
src                      └──────────┘                     └────┘             └────┘
typ                      └──────────┘                  └────┘           └────┘ 
doc                                                       └────┘             └────┘
1382    (s.image f).bind t = s.bind (λa, t (f a)) :=
id      └────┘  └──┘    └───┘        
src      └────┘   └──┘      └───┘
typ     └────┘  └──┘    └───┘        
doc      └────┘   └──┘       └───┘
1383  by haveI := classical.dec_eq α; exact
id               └──────────────┘ 
src     └───────┘└──────────────┘   └────┘
typ     └───────┘└──────────────┘  └────┘
doc     └───────┘                   └────┘
txt     └───────┘                   └────┘
par     └───────┘                   └────┘
pid          └─┘                        
st     └───────────────────────────────────
1384  finset.induction_on s rfl (λ a s has ih,
id   └─────────────────┘  └─┘
src  └─────────────────┘ └─┘  └────────────
typ  └─────────────────┘└─┘  └────────────
doc  └─────────────────┘      └────────────
txt                           └────────────
par                           └────────────
pid                           └────────────
st   ─────────────────────────────────────────
1385    by simp only [image_insert, bind_insert, ih])
id                   └──────────┘  └─────────┘  └┘
src  ─┘  └─────────┘└──────────┘└┘└─────────┘└┘  └─
typ  ─┘  └─────────┘└──────────┘└┘└─────────┘└┘└┘└─
doc  ─┘  └─────────┘            └┘           └┘  └─
txt  ─┘  └─────────┘            └┘           └┘  └─
par  ─┘  └─────────┘            └┘           └┘  └─
pid  ─┘  └──────────┘            └┘           └┘  └┘
st   ───┘└────────────────────────────────────────┘└─
1386  
src  
typ  
doc  
txt  
par  
pid  
st   
1387  theorem bind_image [decidable_eq γ] {s : finset α} {t : α → finset β} {f : β → γ} :
id                       └──────────┘        └────┘           └────┘           
src                      └──────────┘         └────┘             └────┘
typ                      └──────────┘        └────┘           └────┘           
doc                                           └────┘             └────┘
1388    (s.bind t).image f = s.bind (λa, (t a).image f) :=
id      └───┘  └───┘    └───┘        └───┘  
src      └───┘   └───┘      └───┘           └───┘
typ     └───┘  └───┘    └───┘        └───┘  
doc      └───┘   └───┘       └───┘           └───┘
1389  by haveI := classical.dec_eq α; exact
id               └──────────────┘ 
src     └───────┘└──────────────┘   └────┘
typ     └───────┘└──────────────┘  └────┘
doc     └───────┘                   └────┘
txt     └───────┘                   └────┘
par     └───────┘                   └────┘
pid          └─┘                        
st     └───────────────────────────────────
1390  finset.induction_on s rfl (λ a s has ih,
id   └─────────────────┘  └─┘
src  └─────────────────┘ └─┘  └────────────
typ  └─────────────────┘└─┘  └────────────
doc  └─────────────────┘      └────────────
txt                           └────────────
par                           └────────────
pid                           └────────────
st   ─────────────────────────────────────────
1391    by simp only [bind_insert, image_union, ih])
id                   └─────────┘  └─────────┘  └┘
src  ─┘  └─────────┘└─────────┘└┘└─────────┘└┘  └─
typ  ─┘  └─────────┘└─────────┘└┘└─────────┘└┘└┘└─
doc  ─┘  └─────────┘           └┘           └┘  └─
txt  ─┘  └─────────┘           └┘           └┘  └─
par  ─┘  └─────────┘           └┘           └┘  └─
pid  ─┘  └──────────┘           └┘           └┘  └┘
st   ───┘└───────────────────────────────────────┘└─
1392  
src  
typ  
doc  
txt  
par  
pid  
st   
1393  theorem bind_to_finset [decidable_eq α] (s : multiset α) (t : α → multiset β) :
id                           └──────────┘        └──────┘           └──────┘ 
src                          └──────────┘         └──────┘             └──────┘
typ                          └──────────┘        └──────┘           └──────┘ 
doc                                               └──────┘             └──────┘
1394    (s.bind t).to_finset = s.to_finset.bind (λa, (t a).to_finset) :=
id      └───┘  └───────┘   └────────┘└───┘        └───────┘
src      └───┘   └───────┘    └────────┘└───┘           └───────┘
typ     └───┘  └───────┘   └────────┘└───┘        └───────┘
doc      └───┘   └───────┘     └────────┘└───┘           └───────┘
1395  ext.2 $ λ x, by simp only [multiset.mem_to_finset, mem_bind, multiset.mem_bind, exists_prop]
id   └─┘                      └────────────────────┘  └──────┘  └───────────────┘  └─────────┘
src  └─┘            └─────────┘└────────────────────┘└┘└──────┘└┘└───────────────┘└┘└─────────┘└─
typ  └─┘           └─────────┘└────────────────────┘└┘└──────┘└┘└───────────────┘└┘└─────────┘└─
doc                  └─────────┘                      └┘        └┘                 └┘           └─
txt                  └─────────┘                      └┘        └┘                 └┘           └─
par                  └─────────┘                      └┘        └┘                 └┘           └─
pid                      └──┘└┘                      └┘        └┘                 └┘           
st                  └─────────────────────────────────────────────────────────────────────────────
1396  
src  
typ  
doc  
txt  
par  
pid  
st   
1397  lemma bind_mono {t₁ t₂ : α → finset β} (h : ∀a∈s, t₁ a ⊆ t₂ a) : s.bind t₁ ⊆ s.bind t₂ :=
id                               └────┘            └┘   └┘     └───┘ └┘  └───┘ └┘
src                               └────┘                              └───┘      └───┘
typ                              └────┘            └┘   └┘     └───┘ └┘  └───┘ └┘
doc                               └────┘                               └───┘       └───┘
1398  have ∀b a, a ∈ s → b ∈ t₁ a → (∃ (a : α), a ∈ s ∧ b ∈ t₂ a),
id                   └┘                   └┘ 
src                                                
typ                  └┘                   └┘ 
1399    from assume b a ha hb, ⟨a, ha, finset.mem_of_subset (h a ha) hb⟩,
id                   └┘ └┘     └┘  └──────────────────┘    └┘  └┘
src                                   └──────────────────┘
typ                  └┘ └┘     └┘  └──────────────────┘    └┘  └┘
1400  by simpa only [subset_iff, mem_bind, exists_imp_distrib, and_imp, exists_prop]
id                  └────────┘  └──────┘  └────────────────┘  └─────┘  └─────────┘
src     └──────────┘└────────┘└┘└──────┘└┘└────────────────┘└┘└─────┘└┘└─────────┘└─
typ     └──────────┘└────────┘└┘└──────┘└┘└────────────────┘└┘└─────┘└┘└─────────┘└─
doc     └──────────┘          └┘        └┘                  └┘       └┘           └─
txt     └──────────┘          └┘        └┘                  └┘       └┘           └─
par     └──────────┘          └┘        └┘                  └┘       └┘           └─
pid          └──┘└┘          └┘        └┘                  └┘       └┘           
st     └────────────────────────────────────────────────────────────────────────────
1401  
src  
typ  
doc  
txt  
par  
pid  
st   
1402  lemma bind_singleton {f : α → β} : s.bind (λa, {f a}) = s.image f :=
id                                    └───┘          └────┘ 
src                                      └───┘              └────┘
typ                                   └───┘          └────┘ 
doc                                      └───┘                └────┘
1403  ext.2 $ λ x, by simp only [mem_bind, mem_image, insert_empty_eq_singleton, mem_singleton, eq_comm]
id   └─┘                      └──────┘  └───────┘  └───────────────────────┘  └───────────┘  └─────┘
src  └─┘            └─────────┘└──────┘└┘└───────┘└┘└───────────────────────┘└┘└───────────┘└┘└─────┘└─
typ  └─┘           └─────────┘└──────┘└┘└───────┘└┘└───────────────────────┘└┘└───────────┘└┘└─────┘└─
doc                  └─────────┘        └┘         └┘                         └┘             └┘       └─
txt                  └─────────┘        └┘         └┘                         └┘             └┘       └─
par                  └─────────┘        └┘         └┘                         └┘             └┘       └─
pid                      └──┘└┘        └┘         └┘                         └┘             └┘       
st                  └───────────────────────────────────────────────────────────────────────────────────
1404  
src  
typ  
doc  
txt  
par  
pid  
st   
1405  lemma image_bind_filter_eq [decidable_eq α] (s : finset β) (g : β → α) :
id                               └──────────┘        └────┘           
src                              └──────────┘         └────┘
typ                              └──────────┘        └────┘           
doc                                                   └────┘
1406    (s.image g).bind (λa, s.filter $ (λc, g c = a)) = s :=
id      └────┘  └──┘      └─────┘              
src      └────┘   └──┘        └─────┘                 
typ     └────┘  └──┘      └─────┘              
doc      └────┘   └──┘        └─────┘
1407  begin
st   └─────
1408    ext b,
src    └───┘
typ    └───┘
doc    └───┘
txt    └───┘
par    └───┘
pid       └┘
st   ──────┘└─
1409    simp,
src    └──┘
typ    └──┘
doc    └──┘
txt    └──┘
par    └──┘
st   ─────┘└─
1410    split,
src    └───┘
typ    └───┘
doc    └───┘
txt    └───┘
par    └───┘
st   ──────┘└─
1411    { rintros ⟨a, ⟨b', _, _⟩, hb, _⟩, exact hb },
id                                             └┘
src      └────────────────────────────┘  └────┘  
typ      └────────────────────────────┘  └────┘└┘
doc      └────────────────────────────┘  └────┘  
txt      └────────────────────────────┘  └────┘  
par      └────────────────────────────┘  └────┘  
pid             └─────────────────────┘         
st   ───┘└────────────────────────────┘└─────────┘└┘
1412    { rintros hb, exact ⟨g b, ⟨b, hb, rfl⟩, hb, rfl⟩ }
id                                           └┘  └─┘
src      └────────┘  └────┘   └┘  └┘  └┘   └─┘  └┘└─┘└┘
typ      └────────┘  └────┘  └┘ └┘  └┘   └─┘└┘└┘└─┘└┘
doc      └────────┘  └────┘   └┘  └┘  └┘   └─┘  └┘   └┘
txt      └────────┘  └────┘   └┘  └┘  └┘   └─┘  └┘   └┘
par      └────────┘  └────┘   └┘  └┘  └┘   └─┘  └┘   └┘
pid             └─┘          └┘  └┘  └┘   └─┘  └┘   
st   ─────────────┘└───────────────────────────────────┘└─
1413  end
st   ──┘
1414  
1415  end bind
1416  
1417  /-! ### prod-/
1418  section prod
1419  variables {s : finset α} {t : finset β}
id                  └────┘         └────┘
src                 └────┘         └────┘
typ                 └────┘         └────┘
doc                 └────┘         └────┘
1420  
1421  /-- `product s t` is the set of pairs `(a, b)` such that `a ∈ s` and `b ∈ t`. -/
1422  protected def product (s : finset α) (t : finset β) : finset (α × β) := ⟨_, nodup_product s.2 t.2⟩
id                              └────┘        └────┘     └────┘             └───────────┘   
src                             └────┘         └────┘      └────┘               └───────────┘     
typ                             └────┘        └────┘     └────┘             └───────────┘   
doc                             └────┘         └────┘      └────┘
1423  
1424  @[simp] theorem product_val : (s.product t).1 = s.1.product t.1 := rfl
id                                  └──────┘      └─────┘       └─┘
src                                  └──────┘        └─────┘        └─┘
typ                                 └──────┘      └─────┘       └─┘
doc    └──┘                          └──────┘           └─────┘
1425  
1426  @[simp] theorem mem_product {p : α × β} : p ∈ s.product t ↔ p.1 ∈ s ∧ p.2 ∈ t := mem_product
id                                            └──────┘               └─────────┘
src                                               └──────┘                    └─────────┘
typ                                           └──────┘               └─────────┘
doc    └──┘                                         └──────┘
1427  
1428  theorem product_eq_bind [decidable_eq α] [decidable_eq β] (s : finset α) (t : finset β) :
id                            └──────────┘    └──────────┘        └────┘        └────┘ 
src                           └──────────┘     └──────────┘         └────┘         └────┘
typ                           └──────────┘    └──────────┘        └────┘        └────┘ 
doc                                                                 └────┘         └────┘
1429   s.product t = s.bind (λa, t.image $ λb, (a, b)) :=
id    └──────┘   └───┘     └────┘        
src    └──────┘     └───┘       └────┘       
typ   └──────┘   └───┘     └────┘        
doc    └──────┘      └───┘       └────┘
1430  ext.2 $ λ ⟨x, y⟩, by simp only [mem_product, mem_bind, mem_image, exists_prop, prod.mk.inj_iff,
id   └─┘                           └─────────┘  └──────┘  └───────┘  └─────────┘  └─────────────┘
src  └─┘                 └─────────┘└─────────┘└┘└──────┘└┘└───────┘└┘└─────────┘└┘└─────────────┘└─
typ  └─┘                └─────────┘└─────────┘└┘└──────┘└┘└───────┘└┘└─────────┘└┘└─────────────┘└─
doc                       └─────────┘           └┘        └┘         └┘           └┘               └─
txt                       └─────────┘           └┘        └┘         └┘           └┘               └─
par                       └─────────┘           └┘        └┘         └┘           └┘               └─
pid                           └──┘└┘           └┘        └┘         └┘           └┘               └─
st                       └───────────────────────────────────────────────────────────────────────────
1431    and.left_comm, exists_and_distrib_left, exists_eq_right, exists_eq_left]
id     └───────────┘  └─────────────────────┘  └─────────────┘  └────────────┘
src  ─┘└───────────┘└┘└─────────────────────┘└┘└─────────────┘└┘└────────────┘└─
typ  ─┘└───────────┘└┘└─────────────────────┘└┘└─────────────┘└┘└────────────┘└─
doc  ─┘             └┘                       └┘               └┘              └─
txt  ─┘             └┘                       └┘               └┘              └─
par  ─┘             └┘                       └┘               └┘              └─
pid  ─┘             └┘                       └┘               └┘              
st   ───────────────────────────────────────────────────────────────────────────
1432  
src  
typ  
doc  
txt  
par  
pid  
st   
1433  @[simp] theorem card_product (s : finset α) (t : finset β) : card (s.product t) = card s * card t :=
id                                     └────┘        └────┘     └──┘  └──────┘    └──┘   └──┘ 
src                                    └────┘         └────┘      └──┘   └──────┘     └──┘    └──┘
typ                                    └────┘        └────┘     └──┘  └──────┘    └──┘   └──┘ 
doc    └──┘                            └────┘         └────┘      └──┘   └──────┘      └──┘     └──┘
1434  multiset.card_product _ _
id   └───────────────────┘
src  └───────────────────┘
typ  └───────────────────┘
1435  
1436  end prod
1437  
1438  /-! ### sigma -/
1439  section sigma
1440  variables {σ : α → Type*} {s : finset α} {t : Πa, finset (σ a)}
id                                  └────┘            └────┘    
src                                 └────┘             └────┘
typ                                 └────┘            └────┘    
doc                                 └────┘             └────┘
1441  
1442  /-- `sigma s t` is the set of dependent pairs `⟨a, b⟩` such that `a ∈ s` and `b ∈ t a`. -/
1443  protected def sigma (s : finset α) (t : Πa, finset (σ a)) : finset (Σa, σ a) :=
id                            └────┘           └────┘        └────┘    
src                           └────┘             └────┘          └────┘   
typ                           └────┘           └────┘        └────┘    
doc                           └────┘             └────┘          └────┘
1444  ⟨_, nodup_sigma s.2 (λ a, (t a).2)⟩
id       └─────────┘           
src      └─────────┘               
typ      └─────────┘           
1445  
1446  @[simp] theorem mem_sigma {p : sigma σ} : p ∈ s.sigma t ↔ p.1 ∈ s ∧ p.2 ∈ t (p.1) := mem_sigma
id                                  └───┘       └────┘                   └───────┘
src                                 └───┘          └────┘                         └───────┘
typ                                 └───┘       └────┘                   └───────┘
doc    └──┘                                         └────┘
1447  
1448  theorem sigma_mono {s₁ s₂ : finset α} {t₁ t₂ : Πa, finset (σ a)}
id                               └────┘               └────┘   
src                              └────┘                 └────┘
typ                              └────┘               └────┘   
doc                              └────┘                 └────┘
1449    (H1 : s₁ ⊆ s₂) (H2 : ∀a, t₁ a ⊆ t₂ a) : s₁.sigma t₁ ⊆ s₂.sigma t₂ :=
id           └┘  └┘           └┘   └┘     └┘└────┘ └┘  └┘└────┘ └┘
src                                            └────┘       └────┘
typ          └┘  └┘           └┘   └┘     └┘└────┘ └┘  └┘└────┘ └┘
doc                                              └────┘        └────┘
1450  λ ⟨x, sx⟩ H, let ⟨H3, H4⟩ := mem_sigma.1 H in mem_sigma.2 ⟨H1 H3, H2 x H4⟩
id             └─┘  └┘  └┘     └───────┘      └───────┘   └┘     └┘
src                               └───────┘       └───────┘
typ            └─┘  └┘  └┘     └───────┘      └───────┘   └┘     └┘
1451  
1452  theorem sigma_eq_bind [decidable_eq α] [∀a, decidable_eq (σ a)] (s : finset α) (t : Πa, finset (σ a)) :
id                          └──────────┘       └──────────┘           └────┘           └────┘   
src                         └──────────┘         └──────────┘             └────┘             └────┘
typ                         └──────────┘       └──────────┘           └────┘           └────┘   
doc                                                                       └────┘             └────┘
1453   s.sigma t = s.bind (λa, (t a).image $ λb, ⟨a, b⟩) :=
id    └────┘   └───┘        └───┘          
src    └────┘     └───┘           └───┘
typ   └────┘   └───┘        └───┘          
doc    └────┘      └───┘           └───┘
1454  ext.2 $ λ ⟨x, y⟩, by simp only [mem_sigma, mem_bind, mem_image, exists_prop,
id   └─┘                           └───────┘  └──────┘  └───────┘  └─────────┘
src  └─┘                 └─────────┘└───────┘└┘└──────┘└┘└───────┘└┘└─────────┘└─
typ  └─┘                └─────────┘└───────┘└┘└──────┘└┘└───────┘└┘└─────────┘└─
doc                       └─────────┘         └┘        └┘         └┘           └─
txt                       └─────────┘         └┘        └┘         └┘           └─
par                       └─────────┘         └┘        └┘         └┘           └─
pid                           └──┘└┘         └┘        └┘         └┘           └─
st                       └────────────────────────────────────────────────────────
1455    and.left_comm, exists_and_distrib_left, exists_eq_left, heq_iff_eq, exists_eq_right]
id     └───────────┘  └─────────────────────┘  └────────────┘  └────────┘  └─────────────┘
src  ─┘└───────────┘└┘└─────────────────────┘└┘└────────────┘└┘└────────┘└┘└─────────────┘└─
typ  ─┘└───────────┘└┘└─────────────────────┘└┘└────────────┘└┘└────────┘└┘└─────────────┘└─
doc  ─┘             └┘                       └┘              └┘          └┘               └─
txt  ─┘             └┘                       └┘              └┘          └┘               └─
par  ─┘             └┘                       └┘              └┘          └┘               └─
pid  ─┘             └┘                       └┘              └┘          └┘               
st   ───────────────────────────────────────────────────────────────────────────────────────
1456  
src  
typ  
doc  
txt  
par  
pid  
st   
1457  end sigma
1458  
1459  /-! ### pi -/
1460  section pi
1461  variables {δ : α → Type*} [decidable_eq α]
id                              └──────────┘
src                             └──────────┘
typ                             └──────────┘
1462  
1463  def pi (s : finset α) (t : Πa, finset (δ a)) : finset (Πa∈s, δ a) :=
id               └────┘           └────┘        └────┘       
src              └────┘             └────┘          └────┘
typ              └────┘           └────┘        └────┘       
doc              └────┘             └────┘          └────┘
1464  ⟨s.1.pi (λ a, (t a).1), nodup_pi s.2 (λ a _, (t a).2)⟩
id     └┘              └──────┘            
src     └┘                 └──────┘                 
typ    └┘              └──────┘            
doc      └┘
1465  
1466  @[simp] lemma pi_val (s : finset α) (t : Πa, finset (δ a)) :
id                             └────┘           └────┘   
src                            └────┘             └────┘
typ                            └────┘           └────┘   
doc    └──┘                    └────┘             └────┘
1467    (s.pi t).1 = s.1.pi (λ a, (t a).1) := rfl
id      └─┘      └┘                └─┘
src      └─┘        └┘                   └─┘
typ     └─┘      └┘                └─┘
doc                    └┘
1468  
1469  @[simp] lemma mem_pi {s : finset α} {t : Πa, finset (δ a)} {f : Πa∈s, δ a} :
id                             └────┘           └────┘                
src                            └────┘             └────┘
typ                            └────┘           └────┘                
doc    └──┘                    └────┘             └────┘
1470    f ∈ s.pi t ↔ (∀a (h : a ∈ s), f a h ∈ t a) :=
id       └─┘                     
src        └─┘                          
typ      └─┘                     
1471  mem_pi _ _ _
id   └────┘
src  └────┘
typ  └────┘
1472  
1473  def pi.empty (β : α → Sort*) (a : α) (h : a ∈ (∅ : finset α)) : β a :=
id                                                 └────┘       
src                                                   └────┘
typ                                                └────┘       
doc                                                     └────┘
1474  multiset.pi.empty β a h
id   └───────────────┘   
src  └───────────────┘
typ  └───────────────┘   
1475  
1476  def pi.cons (s : finset α) (a : α) (b : δ a) (f : Πa, a ∈ s → δ a) (a' : α) (h : a' ∈ insert a s) : δ a' :=
id                    └────┘                                               └┘  └────┘       └┘
src                   └────┘                                                             └────┘
typ                   └────┘                                               └┘  └────┘       └┘
doc                   └────┘
1477  multiset.pi.cons s.1 a b f _ (multiset.mem_cons.2 $ mem_insert.symm.2 h)
id   └──────────────┘         └───────────────┘    └────────┘└───┘  
src  └──────────────┘             └───────────────┘    └────────┘└───┘
typ  └──────────────┘         └───────────────┘    └────────┘└───┘  
1478  
1479  @[simp] lemma pi.cons_same (s : finset α) (a : α) (b : δ a) (f : Πa, a ∈ s → δ a) (h : a ∈ insert a s) :
id                                   └────┘                                         └────┘  
src                                  └────┘                                                   └────┘
typ                                  └────┘                                         └────┘  
doc    └──┘                          └────┘
1480    pi.cons s a b f a h = b :=
id     └─────┘        
src    └─────┘             
typ    └─────┘        
1481  multiset.pi.cons_same _
id   └───────────────────┘
src  └───────────────────┘
typ  └───────────────────┘
1482  
1483  lemma pi.cons_ne {s : finset α} {a a' : α} {b : δ a} {f : Πa, a ∈ s → δ a} {h : a' ∈ insert a s} (ha : a ≠ a') :
id                         └────┘                                          └┘  └────┘            └┘
src                        └────┘                                                       └────┘              
typ                        └────┘                                          └┘  └────┘            └┘
doc                        └────┘
1484    pi.cons s a b f a' h = f a' ((mem_insert.1 h).resolve_left ha.symm) :=
id     └─────┘     └┘    └┘   └────────┘   └──────────┘  └┘└───┘
src    └─────┘                      └────────┘    └──────────┘    └───┘
typ    └─────┘     └┘    └┘   └────────┘   └──────────┘  └┘└───┘
1485  multiset.pi.cons_ne _ _
id   └─────────────────┘
src  └─────────────────┘
typ  └─────────────────┘
1486  
1487  lemma injective_pi_cons  {a : α} {b : δ a} {s : finset α} (hs : a ∉ s) :
id                                                └────┘           
src                                                  └────┘            
typ                                               └────┘           
doc                                                  └────┘
1488    function.injective (pi.cons s a b) :=
id     └────────────────┘  └─────┘   
src    └────────────────┘  └─────┘
typ    └────────────────┘  └─────┘   
1489  assume e₁ e₂ eq,
id          └┘ └┘ └┘
src               └┘
typ         └┘ └┘ └┘
1490  @multiset.injective_pi_cons α _ δ a b s.1 hs _ _ $
id    └────────────────────────┘         └┘
src   └────────────────────────┘            
typ   └────────────────────────┘         └┘
1491    funext $ assume e, funext $ assume h,
id     └────┘            └────┘          
src    └────┘             └────┘
typ    └────┘            └────┘          
1492    have pi.cons s a b e₁ e (by simpa only [mem_cons, mem_insert] using h) = pi.cons s a b e₂ e (by simpa only [mem_cons, mem_insert] using h),
id          └─────┘    └┘                  └──────┘  └────────┘           └─────┘    └┘                  └──────┘  └────────┘        
src         └─────┘                └──────────┘└──────┘└┘└────────┘└──────┘    └─────┘                └──────────┘└──────┘└┘└────────┘└──────┘
typ         └─────┘    └┘      └──────────┘└──────┘└┘└────────┘└──────┘   └─────┘    └┘      └──────────┘└──────┘└┘└────────┘└──────┘
doc                                └──────────┘        └┘          └──────┘                            └──────────┘        └┘          └──────┘
txt                                └──────────┘        └┘          └──────┘                            └──────────┘        └┘          └──────┘
par                                └──────────┘        └┘          └──────┘                            └──────────┘        └┘          └──────┘
pid                                     └──┘└┘        └┘          └────┘                                 └──┘└┘        └┘          └────┘
st                                └────────────────────────────────────────┘                          └────────────────────────────────────────┘
1493      by rw [eq],
id              └┘
src         └──┘└┘
typ         └──┘└┘
doc         └──┘  
txt         └──┘  
par         └──┘  
pid           └┘  
st         └─────┘
1494    this
id     └──┘
typ    └──┘
1495  
1496  @[simp] lemma pi_empty {t : Πa:α, finset (δ a)} :
id                                    └────┘   
src                                    └────┘
typ                                   └────┘   
doc    └──┘                            └────┘
1497    pi (∅ : finset α) t = singleton (pi.empty δ) := rfl
id     └┘     └────┘     └───────┘  └──────┘      └─┘
src    └┘     └────┘       └───────┘  └──────┘       └─┘
typ    └┘     └────┘     └───────┘  └──────┘      └─┘
doc            └────┘        └───────┘
1498  
1499  @[simp] lemma pi_insert [∀a, decidable_eq (δ a)]
id                               └──────────┘   
src                               └──────────┘
typ                              └──────────┘   
doc    └──┘
1500    {s : finset α} {t : Πa:α, finset (δ a)} {a : α} (ha : a ∉ s) :
id          └────┘             └────┘                     
src         └────┘               └────┘                        
typ         └────┘             └────┘                     
doc         └────┘               └────┘
1501    pi (insert a s) t = (t a).bind (λb, (pi s t).image (pi.cons s a b)) :=
id     └┘  └────┘         └──┘       └┘   └───┘   └─────┘   
src    └┘  └────┘              └──┘        └┘     └───┘   └─────┘
typ    └┘  └────┘         └──┘       └┘   └───┘   └─────┘   
doc                             └──┘               └───┘
1502  begin
st   └─────
1503    apply eq_of_veq,
id           └───────┘
src    └────┘└───────┘
typ    └────┘└───────┘
doc    └────┘
txt    └────┘
par    └────┘
pid         
st   ────────────────┘└─
1504    rw ← multiset.erase_dup_eq_self.2 (pi (insert a s) t).2,
id          └────────────────────────┘    └┘  └────┘    
src    └───┘└────────────────────────┘└─┘ └┘ └────┘  └┘ └─┘
typ    └───┘└────────────────────────┘└─┘ └┘ └────┘└┘└─┘
doc    └───┘                          └─┘            └┘ └─┘
txt    └───┘                          └─┘            └┘ └─┘
par    └───┘                          └─┘            └┘ └─┘
pid      └─┘                          └─┘            └┘ └┘
st   ────────────────────────────────────────────────────────┘└─
1505    refine (λ s' (h : s' = a :: s.1), (_ : erase_dup (multiset.pi s' (λ a, (t a).1)) =
id                             └┘
src    └─────┘  └───────┘   └┘ └───┘ └──┘                         └──┘   └────┘ 
typ    └─────┘  └───────┘   └┘ └───┘ └──┘                         └──┘   └────┘ 
doc    └─────┘  └───────┘    └┘ └───┘ └──┘                         └──┘   └────┘ 
txt    └─────┘  └───────┘       └───┘ └──┘                         └──┘   └────┘ 
par    └─────┘  └───────┘       └───┘ └──┘                         └──┘   └────┘ 
pid            └───────┘       └───┘ └──┘                         └──┘   └────┘ 
st   ─────────────────────────────────────────────────────────────────────────────────────
1506      erase_dup ((t a).1.bind $ λ b,
src  ───┘             └───────┘  └───
typ  ───┘             └───────┘  └───
doc  ───┘             └───────┘  └───
txt  ───┘             └───────┘  └───
par  ───┘             └───────┘  └───
pid  ───┘             └───────┘  └───
st   ───────────────────────────────────
1507      erase_dup $ (multiset.pi s.1 (λ (a : α), (t a).val)).map $
id       └───────┘    └─────────┘                 
src  ───┘└───────┘  └─────────┘ └─┘  └────┘ └─┘   └──────────┘ 
typ  ───┘└───────┘  └─────────┘ └─┘  └────┘└─┘  └──────────┘ 
doc  ───┘└───────┘  └─────────┘ └─┘  └────┘ └─┘   └──────────┘ 
txt  ───┘                       └─┘  └────┘ └─┘   └──────────┘ 
par  ───┘                       └─┘  └────┘ └─┘   └──────────┘ 
pid  ───┘                       └─┘  └────┘ └─┘   └──────────┘ 
st   ───────────────────────────────────────────────────────────────
1508        λ f a' h', multiset.pi.cons s.1 a b f a' (h ▸ h')))) _ (insert_val_of_not_mem ha),
id                    └──────────────┘                          └───────────────────┘ └┘
src  ─────┘ └────────┘└──────────────┘ └─┘         └─────┘ └───────────────────┘  
typ  ─────┘ └────────┘└──────────────┘└─┘        └─────┘ └───────────────────┘└┘
doc  ─────┘ └────────┘                 └─┘          └─────┘                        
txt  ─────┘ └────────┘                 └─┘          └─────┘                        
par  ─────┘ └────────┘                 └─┘          └─────┘                        
pid  ─────┘ └────────┘                 └─┘          └─────┘                        
st   ──────────────────────────────────────────────────────────────────────────────────────┘└─
1509    subst s', rw pi_cons,
id           └┘     └─────┘
src    └────┘    └─┘└─────┘
typ    └────┘└┘  └─┘└─────┘
doc    └────┘    └─┘
txt    └────┘    └─┘
par    └────┘    └─┘
pid               
st   ─────────┘└──────────┘└─
1510    congr, funext b,
src    └───┘  └──────┘
typ    └───┘  └──────┘
doc           └──────┘
txt    └───┘  └──────┘
par    └───┘  └──────┘
pid                 └┘
st   ──────┘└────────┘└─
1511    rw multiset.erase_dup_eq_self.2,
id        └────────────────────────┘
src    └─┘└────────────────────────┘└┘
typ    └─┘└────────────────────────┘└┘
doc    └─┘                          └┘
txt    └─┘                          └┘
par    └─┘                          └┘
pid                                └┘
st   ────────────────────────────────┘└─
1512    exact multiset.nodup_map (multiset.injective_pi_cons ha) (pi s t).2,
id           └────────────────┘  └────────────────────────┘ └┘   └┘  
src    └────┘└────────────────┘ └────────────────────────┘  └┘ └┘  └─┘
typ    └────┘└────────────────┘ └────────────────────────┘└┘└┘ └┘└─┘
doc    └────┘                                               └┘     └─┘
txt    └────┘                                               └┘     └─┘
par    └────┘                                               └┘     └─┘
pid                                                        └┘     └┘
st   ────────────────────────────────────────────────────────────────────┘└─
1513  end
st   ──┘
1514  
1515  end pi
1516  
1517  /-! ### powerset -/
1518  section powerset
1519  
1520  /-- When `s` is a finset, `s.powerset` is the finset of all subsets of `s` (seen as finsets). -/
1521  def powerset (s : finset α) : finset (finset α) :=
id                     └────┘     └────┘  └────┘ 
src                    └────┘      └────┘  └────┘
typ                    └────┘     └────┘  └────┘ 
doc                    └────┘      └────┘  └────┘
1522  ⟨s.1.powerset.pmap finset.mk
id     └──────┘ └──┘  └───────┘
src     └──────┘ └──┘  └───────┘
typ    └──────┘ └──┘  └───────┘
doc               └──┘
1523    (λ t h, nodup_of_le (mem_powerset.1 h) s.2),
id           └─────────┘  └──────────┘    
src            └─────────┘  └──────────┘      
typ          └─────────┘  └──────────┘    
1524   nodup_pmap (λ a ha b hb, congr_arg finset.val)
id    └────────┘     └┘  └┘  └───────┘ └────────┘
src   └────────┘               └───────┘ └────────┘
typ   └────────┘     └┘  └┘  └───────┘ └────────┘
1525     (nodup_powerset.2 s.2)⟩
id       └────────────┘  
src      └────────────┘   
typ      └────────────┘  
1526  
1527  @[simp] theorem mem_powerset {s t : finset α} : s ∈ powerset t ↔ s ⊆ t :=
id                                       └────┘       └──────┘     
src                                      └────┘         └──────┘      
typ                                      └────┘       └──────┘     
doc    └──┘                              └────┘          └──────┘
1528  by cases s; simp only [powerset, mem_mk, mem_pmap, mem_powerset, exists_prop, exists_eq_right]; rw ← val_le_iff
id                         └──────┘  └────┘  └──────┘  └──────────┘  └─────────┘  └─────────────┘        └────────┘
src     └────┘   └─────────┘└──────┘└┘└────┘└┘└──────┘└┘└──────────┘└┘└─────────┘└┘└─────────────┘  └───┘└────────┘
typ     └────┘  └─────────┘└──────┘└┘└────┘└┘└──────┘└┘└──────────┘└┘└─────────┘└┘└─────────────┘  └───┘└────────┘
doc     └────┘   └─────────┘└──────┘└┘      └┘        └┘            └┘           └┘                 └───┘          
txt     └────┘   └─────────┘        └┘      └┘        └┘            └┘           └┘                 └───┘          
par     └────┘   └─────────┘        └┘      └┘        └┘            └┘           └┘                 └───┘          
pid                 └──┘└┘        └┘      └┘        └┘            └┘           └┘                   └─┘          
st     └─────────────────────────────────────────────────────────────────────────────────────────────────────────────
1529  
src  
typ  
doc  
txt  
par  
pid  
st   
1530  @[simp] theorem empty_mem_powerset (s : finset α) : ∅ ∈ powerset s :=
id                                           └────┘       └──────┘ 
src                                          └────┘        └──────┘
typ                                          └────┘       └──────┘ 
doc    └──┘                                  └────┘          └──────┘
1531  mem_powerset.2 (empty_subset _)
id   └──────────┘   └──────────┘
src  └──────────┘   └──────────┘
typ  └──────────┘   └──────────┘
1532  
1533  @[simp] theorem mem_powerset_self (s : finset α) : s ∈ powerset s :=
id                                          └────┘       └──────┘ 
src                                         └────┘         └──────┘
typ                                         └────┘       └──────┘ 
doc    └──┘                                 └────┘          └──────┘
1534  mem_powerset.2 (subset.refl _)
id   └──────────┘   └─────────┘
src  └──────────┘   └─────────┘
typ  └──────────┘   └─────────┘
1535  
1536  @[simp] lemma powerset_empty [decidable_eq α] : finset.powerset (∅ : finset α) = {∅} := rfl
id                                 └──────────┘     └─────────────┘     └────┘         └─┘
src                                └──────────┘      └─────────────┘     └────┘          └─┘
typ                                └──────────┘     └─────────────┘     └────┘         └─┘
doc    └──┘                                          └─────────────┘      └────┘
1537  
1538  @[simp] theorem powerset_mono {s t : finset α} : powerset s ⊆ powerset t ↔ s ⊆ t :=
id                                        └────┘     └──────┘   └──────┘     
src                                       └────┘      └──────┘    └──────┘      
typ                                       └────┘     └──────┘   └──────┘     
doc    └──┘                               └────┘      └──────┘     └──────┘
1539  ⟨λ h, (mem_powerset.1 $ h $ mem_powerset_self _),
id         └──────────┘       └───────────────┘
src         └──────────┘        └───────────────┘
typ        └──────────┘       └───────────────┘
1540   λ st u h, mem_powerset.2 $ subset.trans (mem_powerset.1 h) st⟩
id      └┘    └──────────┘    └──────────┘  └──────────┘    └┘
src             └──────────┘    └──────────┘  └──────────┘
typ     └┘    └──────────┘    └──────────┘  └──────────┘    └┘
1541  
1542  @[simp] theorem card_powerset (s : finset α) :
id                                      └────┘ 
src                                     └────┘
typ                                     └────┘ 
doc    └──┘                             └────┘
1543    card (powerset s) = 2 ^ card s :=
id     └──┘  └──────┘       └──┘ 
src    └──┘  └──────┘        └──┘
typ    └──┘  └──────┘       └──┘ 
doc    └──┘  └──────┘          └──┘
1544  (card_pmap _ _ _).trans (card_powerset s.1)
id    └───────┘       └───┘   └───────────┘ 
src   └───────┘       └───┘   └───────────┘  
typ   └───────┘       └───┘   └───────────┘ 
1545  
1546  lemma not_mem_of_mem_powerset_of_not_mem {s t : finset α} {a : α}
id                                                   └────┘        
src                                                  └────┘
typ                                                  └────┘        
doc                                                  └────┘
1547    (ht : t ∈ s.powerset) (h : a ∉ s) : a ∉ t :=
id             └───────┘               
src              └───────┘                 
typ            └───────┘               
doc               └───────┘
1548  by { apply mt _ h, apply mem_powerset.1 ht }
id              └┘           └──────────┘   └┘
src       └────┘└┘└─┘   └────┘└──────────┘└─┘  
typ       └────┘└┘└─┘  └────┘└──────────┘└─┘└┘
doc       └────┘  └─┘   └────┘            └─┘  
txt       └────┘  └─┘   └────┘            └─┘  
par       └────┘  └─┘   └────┘            └─┘  
pid              └─┘                    └─┘  
st     └─────────────┘└────────────────────────┘└┘
1549  
1550  lemma powerset_insert [decidable_eq α] (s : finset α) (a : α) :
id                          └──────────┘        └────┘        
src                         └──────────┘         └────┘
typ                         └──────────┘        └────┘        
doc                                              └────┘
1551    powerset (insert a s) = s.powerset ∪ s.powerset.image (insert a) :=
id     └──────┘  └────┘     └───────┘  └───────┘└────┘  └────┘ 
src    └──────┘  └────┘        └───────┘   └───────┘└────┘  └────┘
typ    └──────┘  └────┘     └───────┘  └───────┘└────┘  └────┘ 
doc    └──────┘                 └───────┘    └───────┘└────┘
1552  begin
st   └─────
1553    ext t,
src    └───┘
typ    └───┘
doc    └───┘
txt    └───┘
par    └───┘
pid       └┘
st   ──────┘└─
1554    simp only [exists_prop, mem_powerset, mem_image, mem_union, subset_insert_iff],
id                └─────────┘  └──────────┘  └───────┘  └───────┘  └───────────────┘
src    └─────────┘└─────────┘└┘└──────────┘└┘└───────┘└┘└───────┘└┘└───────────────┘
typ    └─────────┘└─────────┘└┘└──────────┘└┘└───────┘└┘└───────┘└┘└───────────────┘
doc    └─────────┘           └┘            └┘         └┘         └┘                 
txt    └─────────┘           └┘            └┘         └┘         └┘                 
par    └─────────┘           └┘            └┘         └┘         └┘                 
pid        └──┘└┘           └┘            └┘         └┘         └┘                 
st   ───────────────────────────────────────────────────────────────────────────────┘└─
1555    by_cases h : a ∈ t,
id                    
src    └───────┘ └─┘ 
typ    └───────┘ └─┘
doc    └───────┘ └─┘  
txt    └───────┘ └─┘  
par    └───────┘ └─┘  
pid             └─┘  
st   ───────────────────┘└─
1556    { split,
src      └───┘
typ      └───┘
doc      └───┘
txt      └───┘
par      └───┘
st   ───┘└───┘└─
1557      { exact λH, or.inr ⟨_, H, insert_erase h⟩ },
id                   └────┘        └──────────┘ 
src        └────┘ └─┘└────┘ └─┘ └┘└──────────┘ └┘
typ        └────┘ └─┘└────┘ └─┘ └┘└──────────┘└┘
doc        └────┘ └─┘       └─┘ └┘             └┘
txt        └────┘ └─┘       └─┘ └┘             └┘
par        └────┘ └─┘       └─┘ └┘             └┘
pid              └─┘       └─┘ └┘             
st   ─────┘└──────────────────────────────────────┘└┘
1558      { intros H,
src        └──────┘
typ        └──────┘
doc        └──────┘
txt        └──────┘
par        └──────┘
pid              └┘
st   ─────────────┘└─
1559        cases H,
id               
src        └────┘
typ        └────┘
doc        └────┘
txt        └────┘
par        └────┘
pid             
st   ────────────┘└─
1560        { exact subset.trans (erase_subset a t) H },
id                 └──────────┘  └──────────┘    
src          └────┘└──────────┘ └──────────┘  └┘ 
typ          └────┘└──────────┘ └──────────┘└┘
doc          └────┘                           └┘ 
txt          └────┘                           └┘ 
par          └────┘                           └┘ 
pid                                          └┘ 
st   ───────┘└──────────────────────────────────────┘└┘
1561        { rcases H with ⟨u, hu⟩,
id                  
src          └─────┘ └───────────┘
typ          └─────┘└───────────┘
doc          └─────┘ └───────────┘
txt          └─────┘ └───────────┘
par          └─────┘ └───────────┘
pid                 └───────────┘
st   ────────────────────────────┘└─
1562          rw ← hu.2,
id                └┘
src          └───┘  └┘
typ          └───┘└┘└┘
doc          └───┘  └┘
txt          └───┘  └┘
par          └───┘  └┘
pid            └─┘  └┘
st   ────────────────┘└─
1563          exact subset.trans (erase_insert_subset a u) hu.1 } } },
id                 └──────────┘  └─────────────────┘    └┘
src          └────┘└──────────┘ └─────────────────┘  └┘  └─┘
typ          └────┘└──────────┘ └─────────────────┘└┘└┘└─┘
doc          └────┘                                  └┘  └─┘
txt          └────┘                                  └┘  └─┘
par          └────┘                                  └┘  └─┘
pid                                                 └┘  └─┘
st   ─────────────────────────────────────────────────────────┘└────┘
1564    { have : ¬ ∃ (u : finset α), u ⊆ s ∧ insert a u = t,
id                      └────┘         └────┘     
src      └─────┘ └────┘└────┘    └────┘  
typ      └─────┘ └────┘└────┘  └────┘ 
doc      └─────┘  └────┘└────┘               
txt      └─────┘  └────┘                     
par      └─────┘  └────┘                     
pid      └───┘└┘  └────┘                     
st   ────────────────────────────────────────────────────┘
1565        by simp [ne.symm (ne_insert_of_not_mem _ _ h)],
id                  └─────┘  └──────────────────┘     
src           └────┘└─────┘ └──────────────────┘└───┘ └┘
typ           └────┘└─────┘ └──────────────────┘└───┘└┘
doc           └────┘                            └───┘ └┘
txt           └────┘                            └───┘ └┘
par           └────┘                            └───┘ └┘
pid                                           └───┘ └┘
st                                                       └─
1566      simp [finset.erase_eq_of_not_mem h, this] }
id             └────────────────────────┘   └──┘
src      └────┘└────────────────────────┘ └┘    └┘
typ      └────┘└────────────────────────┘└┘└──┘└┘
doc      └────┘                           └┘    └┘
txt      └────┘                           └┘    └┘
par      └────┘                           └┘    └┘
pid                                     └┘    
st   ─────────────────────────────────────────────┘└─
1567  end
st   ──┘
1568  
1569  end powerset
1570  
1571  section powerset_len
1572  
1573  def powerset_len (n : ℕ) (s : finset α) : finset (finset α) :=
id                                └────┘     └────┘  └────┘ 
src                               └────┘      └────┘  └────┘
typ                               └────┘     └────┘  └────┘ 
doc                                └────┘      └────┘  └────┘
1574  ⟨(s.1.powerset_len n).pmap finset.mk
id      └──────────┘   └──┘  └───────┘
src      └──────────┘    └──┘  └───────┘
typ     └──────────┘   └──┘  └───────┘
doc                       └──┘
1575    (λ t h, nodup_of_le (mem_powerset_len.1 h).1 s.2),
id           └─────────┘  └──────────────┘     
src            └─────────┘  └──────────────┘       
typ          └─────────┘  └──────────────┘     
1576   nodup_pmap (λ a ha b hb, congr_arg finset.val)
id    └────────┘     └┘  └┘  └───────┘ └────────┘
src   └────────┘               └───────┘ └────────┘
typ   └────────┘     └┘  └┘  └───────┘ └────────┘
1577     (nodup_powerset_len s.2)⟩
id       └────────────────┘ 
src      └────────────────┘  
typ      └────────────────┘ 
1578  
1579  theorem mem_powerset_len {n} {s t : finset α} :
id                                       └────┘ 
src                                      └────┘
typ                                      └────┘ 
doc                                      └────┘
1580    s ∈ powerset_len n t ↔ s ⊆ t ∧ card s = n :=
id       └──────────┘        └──┘   
src       └──────────┘            └──┘   
typ      └──────────┘        └──┘   
doc                                   └──┘
1581  by cases s; simp [powerset_len, val_le_iff.symm]; refl
id                    └──────────┘
src     └────┘   └────┘└──────────┘└┘                 └────
typ     └────┘  └────┘└──────────┘└┘└─────────────┘  └────
doc     └────┘   └────┘            └┘                 └────
txt     └────┘   └────┘            └┘                 └────
par     └────┘   └────┘            └┘                 └────
pid                             └┘                     
st     └────────────────────────────────────────────────────
1582  
src  
typ  
doc  
txt  
par  
pid  
st   
1583  @[simp] theorem powerset_len_mono {n} {s t : finset α} (h : s ⊆ t) :
id                                                └────┘          
src                                               └────┘           
typ                                               └────┘          
doc    └──┘                                       └────┘
1584    powerset_len n s ⊆ powerset_len n t :=
id     └──────────┘    └──────────┘  
src    └──────────┘      └──────────┘
typ    └──────────┘    └──────────┘  
1585  λ u h', mem_powerset_len.2 $
id      └┘  └──────────────┘
src          └──────────────┘
typ     └┘  └──────────────┘
1586    and.imp (λ h₂, subset.trans h₂ h) id (mem_powerset_len.1 h')
id     └─────┘    └┘  └──────────┘ └┘   └┘  └──────────────┘  └┘
src    └─────┘        └──────────┘       └┘  └──────────────┘
typ    └─────┘    └┘  └──────────┘ └┘   └┘  └──────────────┘  └┘
1587  
1588  @[simp] theorem card_powerset_len (n : ℕ) (s : finset α) :
id                                                 └────┘ 
src                                                └────┘
typ                                                └────┘ 
doc    └──┘                                         └────┘
1589    card (powerset_len n s) = nat.choose (card s) n :=
id     └──┘  └──────────┘     └────────┘  └──┘   
src    └──┘  └──────────┘       └────────┘  └──┘
typ    └──┘  └──────────┘     └────────┘  └──┘   
doc    └──┘                      └────────┘  └──┘
1590  (card_pmap _ _ _).trans (card_powerset_len n s.1)
id    └───────┘       └───┘   └───────────────┘  
src   └───────┘       └───┘   └───────────────┘    
typ   └───────┘       └───┘   └───────────────┘  
1591  
1592  end powerset_len
1593  
1594  /-! ### fold -/
1595  section fold
1596  variables (op : β → β → β) [hc : is_commutative β op] [ha : is_associative β op]
id                                    └────────────┘             └────────────┘
src                                   └────────────┘             └────────────┘
typ                                   └────────────┘             └────────────┘
1597  local notation a * b := op a b
1598  include hc ha
1599  
1600  /-- `fold op b f s` folds the commutative associative operation `op` over the
1601    `f`-image of `s`, i.e. `fold (+) b f {1,2,3} = `f 1 + f 2 + f 3 + b`. -/
1602  def fold (b : β) (f : α → β) (s : finset α) : β := (s.1.map f).fold op b
id                                  └────┘           └─┘   └──┘  └┘ 
src                                    └────┘              └─┘    └──┘
typ                                 └────┘           └─┘   └──┘  └┘ 
doc                                    └────┘               └─┘    └──┘
1603  
1604  variables {op} {f : α → β} {b : β} {s : finset α} {a : α}
id                                           └────┘
src                                          └────┘
typ                                          └────┘
doc                                          └────┘
1605  
1606  @[simp] theorem fold_empty : (∅ : finset α).fold op b f = b := rfl
id                                    └────┘  └──┘  └┘        └─┘
src                                   └────┘   └──┘               └─┘
typ                                   └────┘  └──┘  └┘        └─┘
doc    └──┘                            └────┘   └──┘
1607  
1608  @[simp] theorem fold_insert [decidable_eq α] (h : a ∉ s) : (insert a s).fold op b f = f a * s.fold op b f :=
id                                └──────────┘               └────┘   └──┘  └┘       └───┘ └┘  
src                               └──────────┘                  └────┘     └──┘                 └───┘
typ                               └──────────┘               └────┘   └──┘  └┘       └───┘ └┘  
doc    └──┘                                                                 └──┘                  └───┘
1609  by unfold fold; rw [insert_val, ndinsert_of_not_mem h, map_cons, fold_cons_left]
id                       └────────┘  └─────────────────┘   └──────┘  └────────────┘
src     └─────────┘  └──┘└────────┘└┘└─────────────────┘ └┘└──────┘└┘└────────────┘└─
typ     └─────────┘  └──┘└────────┘└┘└─────────────────┘└┘└──────┘└┘└────────────┘└─
doc     └─────────┘  └──┘          └┘                    └┘        └┘              └─
txt     └─────────┘  └──┘          └┘                    └┘        └┘              └─
par     └─────────┘  └──┘          └┘                    └┘        └┘              └─
pid           └───┘    └┘          └┘                    └┘        └┘              
st     └────────────────┘└────────┘└─────────────────────┘└────────┘└──────────────┘
1610  
src  
typ  
doc  
txt  
par  
pid  
st   
1611  @[simp] theorem fold_singleton : (singleton a).fold op b f = f a * b := rfl
id                                     └───────┘  └──┘  └┘           └─┘
src                                    └───────┘   └──┘                     └─┘
typ                                    └───────┘  └──┘  └┘           └─┘
doc    └──┘                            └───────┘   └──┘
1612  
1613  @[simp] theorem fold_map {g : γ ↪ α} {s : finset γ} :
id                                          └────┘ 
src                                           └────┘
typ                                         └────┘ 
doc    └──┘                                    └────┘
1614    (s.map g).fold op b f = s.fold op b (f ∘ g) :=
id      └──┘  └──┘  └┘    └───┘ └┘     
src      └──┘   └──┘           └───┘         
typ     └──┘  └──┘  └┘    └───┘ └┘     
doc             └──┘            └───┘
1615  by simp only [fold, map, multiset.map_map]
id                 └──┘  └─┘  └──────────────┘
src     └─────────┘└──┘└┘└─┘└┘└──────────────┘└─
typ     └─────────┘└──┘└┘└─┘└┘└──────────────┘└─
doc     └─────────┘└──┘└┘   └┘                └─
txt     └─────────┘    └┘   └┘                └─
par     └─────────┘    └┘   └┘                └─
pid         └──┘└┘    └┘   └┘                
st     └────────────────────────────────────────
1616  
src  
typ  
doc  
txt  
par  
pid  
st   
1617  @[simp] theorem fold_image [decidable_eq α] {g : γ → α} {s : finset γ}
id                               └──────────┘                  └────┘ 
src                              └──────────┘                     └────┘
typ                              └──────────┘                  └────┘ 
doc    └──┘                                                       └────┘
1618    (H : ∀ (x ∈ s) (y ∈ s), g x = g y → x = y) : (s.image g).fold op b f = s.fold op b (f ∘ g) :=
id                                      └────┘  └──┘  └┘    └───┘ └┘     
src                                                 └────┘   └──┘           └───┘         
typ                                     └────┘  └──┘  └┘    └───┘ └┘     
doc                                                   └────┘   └──┘            └───┘
1619  by simp only [fold, image_val_of_inj_on H, multiset.map_map]
id                 └──┘  └─────────────────┘   └──────────────┘
src     └─────────┘└──┘└┘└─────────────────┘ └┘└──────────────┘└─
typ     └─────────┘└──┘└┘└─────────────────┘└┘└──────────────┘└─
doc     └─────────┘└──┘└┘                    └┘                └─
txt     └─────────┘    └┘                    └┘                └─
par     └─────────┘    └┘                    └┘                └─
pid         └──┘└┘    └┘                    └┘                
st     └──────────────────────────────────────────────────────────
1620  
src  
typ  
doc  
txt  
par  
pid  
st   
1621  @[congr] theorem fold_congr {g : α → β} (H : ∀ x ∈ s, f x = g x) : s.fold op b f = s.fold op b g :=
id                                                             └───┘ └┘    └───┘ └┘  
src    └───┘                                                            └───┘          └───┘
typ                                                            └───┘ └┘    └───┘ └┘  
doc    └───┘                                                             └───┘           └───┘
1622  by rw [fold, fold, map_congr H]
id          └──┘  └──┘  └───────┘ 
src     └──┘└──┘└┘└──┘└┘└───────┘ └─
typ     └──┘└──┘└┘└──┘└┘└───────┘└─
doc     └──┘└──┘└┘└──┘└┘          └─
txt     └──┘    └┘    └┘          └─
par     └──┘    └┘    └┘          └─
pid       └┘    └┘    └┘          
st     └───────┘└────┘└───────────┘
1623  
src  
typ  
doc  
txt  
par  
pid  
st   
1624  theorem fold_op_distrib {f g : α → β} {b₁ b₂ : β} :
id                                                
typ                                               
1625    s.fold op (b₁ * b₂) (λx, f x * g x) = s.fold op b₁ f * s.fold op b₂ g :=
id     └───┘ └┘  └┘  └┘             └───┘ └┘ └┘   └───┘ └┘ └┘ 
src     └───┘                                └───┘            └───┘
typ    └───┘ └┘  └┘  └┘             └───┘ └┘ └┘   └───┘ └┘ └┘ 
doc     └───┘                                 └───┘            └───┘
st     └────┘
1626  by simp only [fold, fold_distrib]
id                 └──┘  └──────────┘
src     └─────────┘└──┘└┘└──────────┘└─
typ     └─────────┘└──┘└┘└──────────┘└─
doc     └─────────┘└──┘└┘            └─
txt     └─────────┘    └┘            └─
par     └─────────┘    └┘            └─
pid         └──┘└┘    └┘            
st     └───────────────────────────────
1627  
src  
typ  
doc  
txt  
par  
pid  
st   
1628  theorem fold_hom {op' : γ → γ → γ} [is_commutative γ op'] [is_associative γ op']
id                                    └────────────┘  └─┘   └────────────┘  └─┘
src                                      └────────────┘         └────────────┘
typ                                   └────────────┘  └─┘   └────────────┘  └─┘
st                                                       └─┘
1629    {m : β → γ} (hm : ∀x y, m (op x y) = op' (m x) (m y)) :
id                           └┘     └─┘       
src                                       
typ                          └┘     └─┘       
1630    s.fold op' (m b) (λx, m (f x)) = m (s.fold op b f) :=
id     └───┘ └─┘                  └───┘ └┘  
src     └───┘                              └───┘
typ    └───┘ └─┘                  └───┘ └┘  
doc     └───┘                               └───┘
1631  by rw [fold, fold, ← fold_hom op hm, multiset.map_map]
id          └──┘  └──┘    └──────┘ └┘ └┘  └──────────────┘
src     └──┘└──┘└┘└──┘└──┘└──────┘    └┘└──────────────┘└─
typ     └──┘└──┘└┘└──┘└──┘└──────┘└┘└┘└┘└──────────────┘└─
doc     └──┘└──┘└┘└──┘└──┘            └┘                └─
txt     └──┘    └┘    └──┘            └┘                └─
par     └──┘    └┘    └──┘            └┘                └─
pid       └┘    └┘    └──┘            └┘                
st     └───────┘└────┘└────────────────┘└────────────────┘
1632  
src  
typ  
doc  
txt  
par  
pid  
st   
1633  theorem fold_union_inter [decidable_eq α] {s₁ s₂ : finset α} {b₁ b₂ : β} :
id                             └──────────┘            └────┘            
src                            └──────────┘             └────┘
typ                            └──────────┘            └────┘            
doc                                                     └────┘
1634    (s₁ ∪ s₂).fold op b₁ f * (s₁ ∩ s₂).fold op b₂ f = s₁.fold op b₂ f * s₂.fold op b₁ f :=
id      └┘  └┘ └──┘  └┘ └┘    └┘  └┘ └──┘  └┘ └┘   └┘└───┘ └┘ └┘   └┘└───┘ └┘ └┘ 
src            └──┘                    └──┘             └───┘             └───┘
typ     └┘  └┘ └──┘  └┘ └┘    └┘  └┘ └──┘  └┘ └┘   └┘└───┘ └┘ └┘   └┘└───┘ └┘ └┘ 
doc             └──┘                     └──┘              └───┘             └───┘
1635  by unfold fold; rw [← fold_add op, ← map_add, union_val,
id                         └──────┘ └┘    └─────┘  └───────┘
src     └─────────┘  └────┘└──────┘  └──┘└─────┘└┘└───────┘└─
typ     └─────────┘  └────┘└──────┘└┘└──┘└─────┘└┘└───────┘└─
doc     └─────────┘  └────┘          └──┘       └┘         └─
txt     └─────────┘  └────┘          └──┘       └┘         └─
par     └─────────┘  └────┘          └──┘       └┘         └─
pid           └───┘    └──┘          └──┘       └┘         └─
st     └────────────────┘└───────────┘└─────────┘└─────────┘└─
1636       inter_val, union_add_inter, map_add, hc.comm, fold_add]
id        └───────┘  └─────────────┘  └─────┘           └──────┘
src  ────┘└───────┘└┘└─────────────┘└┘└─────┘└┘       └┘└──────┘└─
typ  ────┘└───────┘└┘└─────────────┘└┘└─────┘└┘└─────┘└┘└──────┘└─
doc  ────┘         └┘               └┘       └┘       └┘        └─
txt  ────┘         └┘               └┘       └┘       └┘        └─
par  ────┘         └┘               └┘       └┘       └┘        └─
pid  ────┘         └┘               └┘       └┘       └┘        
st   ─────────────┘└───────────────┘└───────┘└───────┘└────────┘
1637  
src  
typ  
doc  
txt  
par  
pid  
st   
1638  @[simp] theorem fold_insert_idem [decidable_eq α] [hi : is_idempotent β op] :
id                                     └──────────┘         └───────────┘  └┘
src                                    └──────────┘          └───────────┘
typ                                    └──────────┘         └───────────┘  └┘
doc    └──┘
1639    (insert a s).fold op b f = f a * s.fold op b f :=
id      └────┘   └──┘  └┘       └───┘ └┘  
src     └────┘     └──┘                 └───┘
typ     └────┘   └──┘  └┘       └───┘ └┘  
doc                └──┘                  └───┘
1640  by haveI := classical.prop_decidable;
id               └──────────────────────┘
src     └───────┘└──────────────────────┘
typ     └───────┘└──────────────────────┘
doc     └───────┘
txt     └───────┘
par     └───────┘
pid          └─┘
st     └───────────────────────────────────
1641     rw [fold, insert_val', ← fold_erase_dup_idem op, erase_dup_map_erase_dup_eq,
id          └──┘  └─────────┘    └─────────────────┘ └┘  └────────────────────────┘
src     └──┘└──┘└┘└─────────┘└──┘└─────────────────┘  └┘└────────────────────────┘└─
typ     └──┘└──┘└┘└─────────┘└──┘└─────────────────┘└┘└┘└────────────────────────┘└─
doc     └──┘└──┘└┘           └──┘                     └┘                          └─
txt     └──┘    └┘           └──┘                     └┘                          └─
par     └──┘    └┘           └──┘                     └┘                          └─
pid       └┘    └┘           └──┘                     └┘                          └─
st   ──────┘└──┘└───────────┘└────────────────────────┘└──────────────────────────┘└─
1642         fold_erase_dup_idem op]; simp only [map_cons, fold_cons_left, fold]
id          └─────────────────┘ └┘              └──────┘  └────────────┘  └──┘
src  ──────┘└─────────────────┘    └─────────┘└──────┘└┘└────────────┘└┘└──┘└─
typ  ──────┘└─────────────────┘└┘  └─────────┘└──────┘└┘└────────────┘└┘└──┘└─
doc  ──────┘                       └─────────┘        └┘              └┘└──┘└─
txt  ──────┘                       └─────────┘        └┘              └┘    └─
par  ──────┘                       └─────────┘        └┘              └┘    └─
pid  ──────┘                           └──┘└┘        └┘              └┘    
st   ────────────────────────────┘└────────────────────────────────────────────
1643  
src  
typ  
doc  
txt  
par  
pid  
st   
1644  lemma fold_op_rel_iff_and [decidable_eq α]
id                              └──────────┘ 
src                             └──────────┘
typ                             └──────────┘ 
1645    {r : β → β → Prop} (hr : ∀ {x y z}, r x (op y z) ↔ (r x y ∧ r x z)) {c : β} :
id                                       └┘                    
src                                                             
typ                                      └┘                    
1646    r c (s.fold op b f) ↔ (r c b ∧ ∀ x∈s, r c (f x)) :=
id        └───┘ └┘                   
src          └───┘                 
typ       └───┘ └┘                   
doc          └───┘
1647  begin
st   └─────
1648    apply finset.induction_on s, { simp },
id           └─────────────────┘ 
src    └────┘└─────────────────┘     └───┘
typ    └────┘└─────────────────┘    └───┘
doc    └────┘└─────────────────┘     └───┘
txt    └────┘                        └───┘
par    └────┘                        └───┘
pid                                     
st   ────────────────────────────┘└──┘└───┘└┘
1649    clear s, intros a s ha IH,
src    └─────┘  └──────────────┘
typ    └─────┘  └──────────────┘
doc    └─────┘  └──────────────┘
txt    └─────┘  └──────────────┘
par    └─────┘  └──────────────┘
pid         └┘        └────────┘
st   ────────┘└────────────────┘└─
1650    rw [finset.fold_insert ha, hr, IH, ← and_assoc, and_comm (r c (f a)), and_assoc],
id         └────────────────┘ └┘      └┘    └───────┘  └──────┘          └───────┘
src    └──┘└────────────────┘  └┘  └┘  └──┘└───────┘└┘└──────┘      └──┘└───────┘
typ    └──┘└────────────────┘└┘└┘└┘└┘└┘└──┘└───────┘└┘└──────┘  └──┘└───────┘
doc    └──┘                    └┘  └┘  └──┘         └┘              └──┘         
txt    └──┘                    └┘  └┘  └──┘         └┘              └──┘         
par    └──┘                    └┘  └┘  └──┘         └┘              └──┘         
pid      └┘                    └┘  └┘  └──┘         └┘              └──┘         
st   ──────────────────────────┘└──┘└──┘└───────────┘└────────────────────┘└─────────┘└──
1651    apply and_congr iff.rfl,
id           └───────┘ └─────┘
src    └────┘└───────┘└─────┘
typ    └────┘└───────┘└─────┘
doc    └────┘         
txt    └────┘         
par    └────┘         
pid                  
st   ────────────────────────┘└─
1652    split,
src    └───┘
typ    └───┘
doc    └───┘
txt    └───┘
par    └───┘
st   ──────┘└─
1653    { rintro ⟨h₁, h₂⟩, intros b hb, rw finset.mem_insert at hb,
id                                        └───────────────┘
src      └─────────────┘  └─────────┘  └─┘└───────────────┘└────┘
typ      └─────────────┘  └─────────┘  └─┘└───────────────┘└────┘
doc      └─────────────┘  └─────────┘  └─┘                 └────┘
txt      └─────────────┘  └─────────┘  └─┘                 └────┘
par      └─────────────┘  └─────────┘  └─┘                 └────┘
pid            └───────┘        └───┘                     └────┘
st   ───┘└─────────────┘└───────────┘└──────────────────────────┘└─
1654      rcases hb with rfl|hb; solve_by_elim },
id              └┘
src      └─────┘  └──────────┘  └────────────┘
typ      └─────┘└┘└──────────┘  └────────────┘
doc      └─────┘  └──────────┘  └────────────┘
txt      └─────┘  └──────────┘  └────────────┘
par      └─────┘  └──────────┘  └────────────┘
pid              └──────────┘               
st   ────────────────────────────────────────┘└┘
1655    { intro h, split,
src      └─────┘  └───┘
typ      └─────┘  └───┘
doc      └─────┘  └───┘
txt      └─────┘  └───┘
par      └─────┘  └───┘
pid           └┘
st   ──────────┘└─────┘└─
1656      { exact h a (finset.mem_insert_self _ _), },
id                  └────────────────────┘
src        └────┘   └────────────────────┘└───┘
typ        └────┘ └────────────────────┘└───┘
doc        └────┘                         └───┘
txt        └────┘                         └───┘
par        └────┘                         └───┘
pid                                      └───┘
st   ─────┘└────────────────────────────────────┘└──┘
1657      { intros b hb, apply h b, rw finset.mem_insert, right, exact hb } }
id                                  └───────────────┘               └┘
src        └─────────┘  └────┘    └─┘└───────────────┘  └───┘  └────┘  
typ        └─────────┘  └────┘  └─┘└───────────────┘  └───┘  └────┘└┘
doc        └─────────┘  └────┘    └─┘                   └───┘  └────┘  
txt        └─────────┘  └────┘    └─┘                   └───┘  └────┘  
par        └─────────┘  └────┘    └─┘                   └───┘  └────┘  
pid              └───┘                                              
st   ────────────────┘└─────────┘└────────────────────┘└─────┘└─────────┘└───
1658  end
st   ──┘
1659  
1660  lemma fold_op_rel_iff_or [decidable_eq α]
id                             └──────────┘ 
src                            └──────────┘
typ                            └──────────┘ 
1661    {r : β → β → Prop} (hr : ∀ {x y z}, r x (op y z) ↔ (r x y ∨ r x z)) {c : β} :
id                                       └┘                    
src                                                             
typ                                      └┘                    
1662    r c (s.fold op b f) ↔ (r c b ∨ ∃ x∈s, r c (f x)) :=
id        └───┘ └┘                 
src          └───┘                      
typ       └───┘ └┘                 
doc          └───┘
1663  begin
st   └─────
1664    apply finset.induction_on s, { simp },
id           └─────────────────┘ 
src    └────┘└─────────────────┘     └───┘
typ    └────┘└─────────────────┘    └───┘
doc    └────┘└─────────────────┘     └───┘
txt    └────┘                        └───┘
par    └────┘                        └───┘
pid                                     
st   ────────────────────────────┘└──┘└───┘└┘
1665    clear s, intros a s ha IH,
src    └─────┘  └──────────────┘
typ    └─────┘  └──────────────┘
doc    └─────┘  └──────────────┘
txt    └─────┘  └──────────────┘
par    └─────┘  └──────────────┘
pid         └┘        └────────┘
st   ────────┘└────────────────┘└─
1666    rw [finset.fold_insert ha, hr, IH, ← or_assoc, or_comm (r c (f a)), or_assoc],
id         └────────────────┘ └┘      └┘    └──────┘  └─────┘          └──────┘
src    └──┘└────────────────┘  └┘  └┘  └──┘└──────┘└┘└─────┘      └──┘└──────┘
typ    └──┘└────────────────┘└┘└┘└┘└┘└┘└──┘└──────┘└┘└─────┘  └──┘└──────┘
doc    └──┘                    └┘  └┘  └──┘        └┘             └──┘        
txt    └──┘                    └┘  └┘  └──┘        └┘             └──┘        
par    └──┘                    └┘  └┘  └──┘        └┘             └──┘        
pid      └┘                    └┘  └┘  └──┘        └┘             └──┘        
st   ──────────────────────────┘└──┘└──┘└──────────┘└───────────────────┘└────────┘└──
1667    apply or_congr iff.rfl,
id           └──────┘ └─────┘
src    └────┘└──────┘└─────┘
typ    └────┘└──────┘└─────┘
doc    └────┘        
txt    └────┘        
par    └────┘        
pid                 
st   ───────────────────────┘└─
1668    split,
src    └───┘
typ    └───┘
doc    └───┘
txt    └───┘
par    └───┘
st   ──────┘└─
1669    { rintro (h₁|⟨x, hx, h₂⟩),
src      └─────────────────────┘
typ      └─────────────────────┘
doc      └─────────────────────┘
txt      └─────────────────────┘
par      └─────────────────────┘
pid            └───────────────┘
st   ───┘└─────────────────────┘└─
1670      { use a, simp [h₁] },
id                     └┘
src        └──┘   └────┘  └┘
typ        └──┘  └────┘└┘└┘
doc        └──┘   └────┘  └┘
txt        └──┘   └────┘  └┘
par        └──┘   └────┘  └┘
pid                    
st   ─────┘└───┘└──────────┘└┘
1671      { refine ⟨x, by simp [hx], h₂⟩ } },
id                            └┘   └┘
src        └─────┘  └┘  └────┘  └┘  └┘
typ        └─────┘ └┘  └────┘└┘└┘└┘└┘
doc        └─────┘  └┘  └────┘  └┘  └┘
txt        └─────┘  └┘  └────┘  └┘  └┘
par        └─────┘  └┘  └────┘  └┘  └┘
pid                └┘  └─────┘  └─┘  
st   ──────────────────┘└────────┘└────┘└──┘
1672    { rintro ⟨x, hx, h⟩,
src      └───────────────┘
typ      └───────────────┘
doc      └───────────────┘
txt      └───────────────┘
par      └───────────────┘
pid            └─────────┘
st   ────────────────────┘└─
1673      rw mem_insert at hx, cases hx,
id          └────────┘              └┘
src      └─┘└────────┘└────┘  └────┘
typ      └─┘└────────┘└────┘  └────┘└┘
doc      └─┘          └────┘  └────┘
txt      └─┘          └────┘  └────┘
par      └─┘          └────┘  └────┘
pid                  └────┘       
st   ──────────────────────┘└────────┘└─
1674      { left, rwa hx at h },
id                   └┘
src        └──┘  └──┘  └────┘
typ        └──┘  └──┘└┘└────┘
doc        └──┘  └──┘  └────┘
txt        └──┘  └──┘  └────┘
par        └──┘  └──┘  └────┘
pid                   └───┘
st   ─────┘└──┘└────────────┘└┘
1675      { right, exact ⟨x, hx, h⟩ } }
id                         └┘  
src        └───┘  └────┘  └┘  └┘ └┘
typ        └───┘  └────┘ └┘└┘└┘└┘
doc        └───┘  └────┘  └┘  └┘ └┘
txt        └───┘  └────┘  └┘  └┘ └┘
par        └───┘  └────┘  └┘  └┘ └┘
pid                      └┘  └┘ 
st   ──────────┘└─────────────────┘└───
1676  end
st   ──┘
1677  
1678  omit hc ha
1679  
1680  section order
1681  variables [decidable_eq α] [decidable_linear_order β] (c : β)
id              └──────────┘     └────────────────────┘
src             └──────────┘     └────────────────────┘
typ             └──────────┘     └────────────────────┘
1682  
1683  lemma le_fold_min : c ≤ s.fold min b f ↔ (c ≤ b ∧ ∀ x∈s, c ≤ f x) :=
id                         └───┘ └─┘                 
src                          └───┘ └─┘                      
typ                        └───┘ └─┘                 
doc                           └───┘
1684  fold_op_rel_iff_and $ λ x y z, le_min_iff
id   └─────────────────┘         └────────┘
src  └─────────────────┘            └────────┘
typ  └─────────────────┘         └────────┘
1685  
1686  lemma fold_min_le : s.fold min b f ≤ c ↔ (b ≤ c ∨ ∃ x∈s, f x ≤ c) :=
id                       └───┘ └─┘                 
src                       └───┘ └─┘                         
typ                      └───┘ └─┘                 
doc                       └───┘
1687  begin
st   └─────
1688    show _ ≥ _ ↔ _,
id            
src    └─────┘└─┘ └┘
typ    └─────┘└─┘ └┘
doc    └─────┘ └─┘ └┘
txt    └─────┘ └─┘ └┘
par    └─────┘ └─┘ └┘
pid    └─────┘ └─┘ └┘
st   ───────────────┘└─
1689    apply fold_op_rel_iff_or,
id           └────────────────┘
src    └────┘└────────────────┘
typ    └────┘└────────────────┘
doc    └────┘
txt    └────┘
par    └────┘
pid         
st   ─────────────────────────┘└─
1690    intros x y z,
src    └──────────┘
typ    └──────────┘
doc    └──────────┘
txt    └──────────┘
par    └──────────┘
pid          └────┘
st   ─────────────┘└─
1691    show _ ≤ _ ↔ _,
id            
src    └─────┘└─┘ └┘
typ    └─────┘└─┘ └┘
doc    └─────┘ └─┘ └┘
txt    └─────┘ └─┘ └┘
par    └─────┘ └─┘ └┘
pid    └─────┘ └─┘ └┘
st   ───────────────┘└─
1692    exact min_le_iff
id           └────────┘
src    └────┘└────────┘
typ    └────┘└────────┘
doc    └────┘          
txt    └────┘          
par    └────┘          
pid                   
st   ──────────────────┘
1693  end
st   └─┘
1694  
1695  lemma lt_fold_min : c < s.fold min b f ↔ (c < b ∧ ∀ x∈s, c < f x) :=
id                         └───┘ └─┘                 
src                          └───┘ └─┘                      
typ                        └───┘ └─┘                 
doc                           └───┘
1696  fold_op_rel_iff_and $ λ x y z, lt_min_iff
id   └─────────────────┘         └────────┘
src  └─────────────────┘            └────────┘
typ  └─────────────────┘         └────────┘
1697  
1698  lemma fold_min_lt : s.fold min b f < c ↔ (b < c ∨ ∃ x∈s, f x < c) :=
id                       └───┘ └─┘                 
src                       └───┘ └─┘                         
typ                      └───┘ └─┘                 
doc                       └───┘
1699  begin
st   └─────
1700    show _ > _ ↔ _,
id            
src    └─────┘└─┘ └┘
typ    └─────┘└─┘ └┘
doc    └─────┘ └─┘ └┘
txt    └─────┘ └─┘ └┘
par    └─────┘ └─┘ └┘
pid    └─────┘ └─┘ └┘
st   ───────────────┘└─
1701    apply fold_op_rel_iff_or,
id           └────────────────┘
src    └────┘└────────────────┘
typ    └────┘└────────────────┘
doc    └────┘
txt    └────┘
par    └────┘
pid         
st   ─────────────────────────┘└─
1702    intros x y z,
src    └──────────┘
typ    └──────────┘
doc    └──────────┘
txt    └──────────┘
par    └──────────┘
pid          └────┘
st   ─────────────┘└─
1703    show _ < _ ↔ _,
id            
src    └─────┘└─┘ └┘
typ    └─────┘└─┘ └┘
doc    └─────┘ └─┘ └┘
txt    └─────┘ └─┘ └┘
par    └─────┘ └─┘ └┘
pid    └─────┘ └─┘ └┘
st   ───────────────┘└─
1704    exact min_lt_iff
id           └────────┘
src    └────┘└────────┘
typ    └────┘└────────┘
doc    └────┘          
txt    └────┘          
par    └────┘          
pid                   
st   ──────────────────┘
1705  end
st   └─┘
1706  
1707  lemma fold_max_le : s.fold max b f ≤ c ↔ (b ≤ c ∧ ∀ x∈s, f x ≤ c) :=
id                       └───┘ └─┘                   
src                       └───┘ └─┘                           
typ                      └───┘ └─┘                   
doc                       └───┘
1708  begin
st   └─────
1709    show _ ≥ _ ↔ _,
id            
src    └─────┘└─┘ └┘
typ    └─────┘└─┘ └┘
doc    └─────┘ └─┘ └┘
txt    └─────┘ └─┘ └┘
par    └─────┘ └─┘ └┘
pid    └─────┘ └─┘ └┘
st   ───────────────┘└─
1710    apply fold_op_rel_iff_and,
id           └─────────────────┘
src    └────┘└─────────────────┘
typ    └────┘└─────────────────┘
doc    └────┘
txt    └────┘
par    └────┘
pid         
st   ──────────────────────────┘└─
1711    intros x y z,
src    └──────────┘
typ    └──────────┘
doc    └──────────┘
txt    └──────────┘
par    └──────────┘
pid          └────┘
st   ─────────────┘└─
1712    show _ ≤ _ ↔ _,
id            
src    └─────┘└─┘ └┘
typ    └─────┘└─┘ └┘
doc    └─────┘ └─┘ └┘
txt    └─────┘ └─┘ └┘
par    └─────┘ └─┘ └┘
pid    └─────┘ └─┘ └┘
st   ───────────────┘└─
1713    exact max_le_iff
id           └────────┘
src    └────┘└────────┘
typ    └────┘└────────┘
doc    └────┘          
txt    └────┘          
par    └────┘          
pid                   
st   ──────────────────┘
1714  end
st   └─┘
1715  
1716  lemma le_fold_max : c ≤ s.fold max b f ↔ (c ≤ b ∨ ∃ x∈s, c ≤ f x) :=
id                         └───┘ └─┘               
src                          └───┘ └─┘                    
typ                        └───┘ └─┘               
doc                           └───┘
1717  fold_op_rel_iff_or $ λ x y z, le_max_iff
id   └────────────────┘         └────────┘
src  └────────────────┘            └────────┘
typ  └────────────────┘         └────────┘
1718  
1719  lemma fold_max_lt : s.fold max b f < c ↔ (b < c ∧ ∀ x∈s, f x < c) :=
id                       └───┘ └─┘                   
src                       └───┘ └─┘                           
typ                      └───┘ └─┘                   
doc                       └───┘
1720  begin
st   └─────
1721    show _ > _ ↔ _,
id            
src    └─────┘└─┘ └┘
typ    └─────┘└─┘ └┘
doc    └─────┘ └─┘ └┘
txt    └─────┘ └─┘ └┘
par    └─────┘ └─┘ └┘
pid    └─────┘ └─┘ └┘
st   ───────────────┘└─
1722    apply fold_op_rel_iff_and,
id           └─────────────────┘
src    └────┘└─────────────────┘
typ    └────┘└─────────────────┘
doc    └────┘
txt    └────┘
par    └────┘
pid         
st   ──────────────────────────┘└─
1723    intros x y z,
src    └──────────┘
typ    └──────────┘
doc    └──────────┘
txt    └──────────┘
par    └──────────┘
pid          └────┘
st   ─────────────┘└─
1724    show _ < _ ↔ _,
id            
src    └─────┘└─┘ └┘
typ    └─────┘└─┘ └┘
doc    └─────┘ └─┘ └┘
txt    └─────┘ └─┘ └┘
par    └─────┘ └─┘ └┘
pid    └─────┘ └─┘ └┘
st   ───────────────┘└─
1725    exact max_lt_iff
id           └────────┘
src    └────┘└────────┘
typ    └────┘└────────┘
doc    └────┘          
txt    └────┘          
par    └────┘          
pid                   
st   ──────────────────┘
1726  end
st   └─┘
1727  
1728  lemma lt_fold_max : c < s.fold max b f ↔ (c < b ∨ ∃ x∈s, c < f x) :=
id                         └───┘ └─┘               
src                          └───┘ └─┘                    
typ                        └───┘ └─┘               
doc                           └───┘
1729  fold_op_rel_iff_or $ λ x y z, lt_max_iff
id   └────────────────┘         └────────┘
src  └────────────────┘            └────────┘
typ  └────────────────┘         └────────┘
1730  
1731  end order
1732  
1733  end fold
1734  
1735  /-! ### sup -/
1736  section sup
1737  variables [semilattice_sup_bot α]
id              └─────────────────┘
src             └─────────────────┘
typ             └─────────────────┘
doc             └─────────────────┘
1738  
1739  /-- Supremum of a finite set: `sup {a, b, c} f = f a ⊔ f b ⊔ f c` -/
1740  def sup (s : finset β) (f : β → α) : α := s.fold (⊔) ⊥ f
id                └────┘                   └───┘     
src               └────┘                        └───┘    
typ               └────┘                   └───┘     
doc               └────┘                        └───┘
1741  
1742  variables {s s₁ s₂ : finset β} {f : β → α}
id                        └────┘
src                       └────┘
typ                       └────┘
doc                       └────┘
1743  
1744  lemma sup_val : s.sup f = (s.1.map f).sup := rfl
id                   └──┘     └─┘   └─┘     └─┘
src                   └──┘       └─┘    └─┘     └─┘
typ                  └──┘     └─┘   └─┘     └─┘
doc                   └──┘         └─┘    └─┘
1745  
1746  @[simp] lemma sup_empty : (∅ : finset β).sup f = ⊥ :=
id                                 └────┘  └─┘    
src                                └────┘   └─┘     
typ                                └────┘  └─┘    
doc    └──┘                         └────┘   └─┘
1747  fold_empty
id   └────────┘
src  └────────┘
typ  └────────┘
1748  
1749  @[simp] lemma sup_insert [decidable_eq β] {b : β} : (insert b s : finset β).sup f = f b ⊔ s.sup f :=
id                             └──────────┘             └────┘     └────┘  └─┘       └──┘ 
src                            └──────────┘               └────┘       └────┘   └─┘           └──┘
typ                            └──────────┘             └────┘     └────┘  └─┘       └──┘ 
doc    └──┘                                                            └────┘   └─┘             └──┘
1750  fold_insert_idem
id   └──────────────┘
src  └──────────────┘
typ  └──────────────┘
1751  
1752  @[simp] lemma sup_singleton [decidable_eq β] {b : β} : ({b} : finset β).sup f = f b :=
id                                └──────────┘                 └────┘  └─┘     
src                               └──────────┘                    └────┘   └─┘    
typ                               └──────────┘                 └────┘  └─┘     
doc    └──┘                                                        └────┘   └─┘
1753  calc _ = f b ⊔ (∅:finset β).sup f : sup_insert
id                 └────┘  └─┘     └────────┘
src                  └────┘   └─┘      └────────┘
typ                └────┘  └─┘     └────────┘
doc                    └────┘   └─┘
1754    ... = f b : sup_bot_eq
id               └────────┘
src                └────────┘
typ              └────────┘
1755  
1756  lemma sup_union [decidable_eq β] : (s₁ ∪ s₂).sup f = s₁.sup f ⊔ s₂.sup f :=
id                    └──────────┘      └┘  └┘ └─┘    └┘└──┘   └┘└──┘ 
src                   └──────────┘              └─┘       └──┘      └──┘
typ                   └──────────┘      └┘  └┘ └─┘    └┘└──┘   └┘└──┘ 
doc                                              └─┘        └──┘       └──┘
1757  finset.induction_on s₁ (by rw [empty_union, sup_empty, bot_sup_eq]) $ λ a s has ih,
id   └─────────────────┘ └┘         └─────────┘  └───────┘  └────────┘         └─┘ └┘
src  └─────────────────┘        └──┘└─────────┘└┘└───────┘└┘└────────┘
typ  └─────────────────┘ └┘     └──┘└─────────┘└┘└───────┘└┘└────────┘        └─┘ └┘
doc  └─────────────────┘        └──┘           └┘         └┘          
txt                             └──┘           └┘         └┘          
par                             └──┘           └┘         └┘          
pid                               └┘           └┘         └┘          
st                             └──────────────┘└─────────┘└──────────┘
1758  by rw [insert_union, sup_insert, sup_insert, ih, sup_assoc]
id          └──────────┘  └────────┘  └────────┘  └┘  └───────┘
src     └──┘└──────────┘└┘└────────┘└┘└────────┘└┘  └┘└───────┘└─
typ     └──┘└──────────┘└┘└────────┘└┘└────────┘└┘└┘└┘└───────┘└─
doc     └──┘            └┘          └┘          └┘  └┘         └─
txt     └──┘            └┘          └┘          └┘  └┘         └─
par     └──┘            └┘          └┘          └┘  └┘         └─
pid       └┘            └┘          └┘          └┘  └┘         
st     └───────────────┘└──────────┘└──────────┘└──┘└─────────┘
1759  
src  
typ  
doc  
txt  
par  
pid  
st   
1760  theorem sup_congr {f g : β → α} (hs : s₁ = s₂) (hfg : ∀a∈s₂, f a = g a) : s₁.sup f = s₂.sup g :=
id                                       └┘  └┘           └┘          └┘└──┘   └┘└──┘ 
src                                                                            └──┘      └──┘
typ                                      └┘  └┘           └┘          └┘└──┘   └┘└──┘ 
doc                                                                              └──┘       └──┘
1761  by subst hs; exact finset.fold_congr hfg
id            └┘        └───────────────┘ └─┘
src     └────┘    └────┘└───────────────┘   
typ     └────┘└┘  └────┘└───────────────┘└─┘
doc     └────┘    └────┘                    
txt     └────┘    └────┘                    
par     └────┘    └────┘                    
pid                                       
st     └──────────────────────────────────────
1762  
src  
typ  
doc  
txt  
par  
pid  
st   
1763  lemma sup_mono_fun {g : β → α} : (∀b∈s, f b ≤ g b) → s.sup f ≤ s.sup g :=
id                                               └──┘   └──┘ 
src                                                       └──┘     └──┘
typ                                              └──┘   └──┘ 
doc                                                        └──┘      └──┘
1764  by letI := classical.dec_eq β; from
id              └──────────────┘ 
src     └──────┘└──────────────┘   └───┘
typ     └──────┘└──────────────┘  └───┘
doc     └──────┘                   └───┘
txt     └──────┘                   └───┘
par     └──────┘                   └───┘
pid         └─┘                   └───┘
st     └─────────────────────────────────
1765  finset.induction_on s (λ _, le_refl _) (λ a s has ih H,
id   └─────────────────┘        └─────┘
src  └─────────────────┘   └──┘└─────┘└──┘  └──────────────
typ  └─────────────────┘  └──┘└─────┘└──┘  └──────────────
doc  └─────────────────┘   └──┘       └──┘  └──────────────
txt                        └──┘       └──┘  └──────────────
par                        └──┘       └──┘  └──────────────
pid                        └──┘       └──┘  └──────────────
st   ────────────────────────────────────────────────────────
1766    by simp only [mem_insert, or_imp_distrib, forall_and_distrib, forall_eq] at H;
id                   └────────┘  └────────────┘  └────────────────┘  └───────┘
src  ─┘  └─────────┘└────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└────┘└─
typ  ─┘  └─────────┘└────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└────┘└─
doc  ─┘  └─────────┘          └┘              └┘                  └┘         └────┘└─
txt  ─┘  └─────────┘          └┘              └┘                  └┘         └────┘└─
par  ─┘  └─────────┘          └┘              └┘                  └┘         └────┘└─
pid  ─┘  └──────────┘          └┘              └┘                  └┘         └───────
st   ───┘└────────────────────────────────────────────────────────────────────────────
1767       simp only [sup_insert]; exact sup_le_sup H.1 (ih H.2))
id                   └────────┘         └────────┘      └┘ 
src  ────┘└─────────┘└────────┘└┘└────┘└────────┘ └─┘    └─┘└─
typ  ────┘└─────────┘└────────┘└──────┘└────────┘ └─┘ └┘└────
doc  ────┘└─────────┘          └┘└────┘           └─┘    └─┘└─
txt  ────┘└─────────┘          └┘└────┘           └─┘    └─┘└─
par  ────┘└─────────┘          └──────┘           └─┘    └────
pid  ───────────────┘          └───────┘           └─┘    └──┘
st   ─────────────────────────────────────────────────────────┘└─
1768  
src  
typ  
doc  
txt  
par  
pid  
st   
1769  lemma le_sup {b : β} (hb : b ∈ s) : f b ≤ s.sup f :=
id                                      └──┘ 
src                                           └──┘
typ                                     └──┘ 
doc                                             └──┘
1770  by letI := classical.dec_eq β; from
id              └──────────────┘ 
src     └──────┘└──────────────┘   └───┘
typ     └──────┘└──────────────┘  └───┘
doc     └──────┘                   └───┘
txt     └──────┘                   └───┘
par     └──────┘                   └───┘
pid         └─┘                   └───┘
st     └─────────────────────────────────
1771  calc f b ≤ f b ⊔ s.sup f : le_sup_left
id                  └───┘    └─────────┘
src           └───┘ └─┘└─────────┘
typ          └───┘└─┘└─────────┘
doc            └───┘ └─┘           
txt                  └─┘           
par                  └─┘           
pid                  └─┘           
st   ───────────────────────────────────────
1772    ... = (insert b s).sup f : sup_insert.symm
id            └────┘              └─────────────┘
src  ─────┘  └────┘  └────┘ └─┘└─────────────┘
typ  ─────┘  └────┘  └────┘ └─┘└─────────────┘
doc  ─────┘          └────┘ └─┘               
txt  ─────┘          └────┘ └─┘               
par  ─────┘          └────┘ └─┘               
pid  ─────┘          └────┘ └─┘               
st   ─────────────────────────────────────────────
1773    ... = s.sup f : by rw [insert_eq_of_mem hb]
id                            └──────────────┘ └┘
src  ─────┘       └─┘  └──┘└──────────────┘  └─
typ  ─────┘       └─┘  └──┘└──────────────┘└┘└─
doc  ─────┘       └─┘  └──┘                  └─
txt  ─────┘       └─┘  └──┘                  └─
par  ─────┘       └─┘  └──┘                  └─
pid  ─────┘       └─┘  └───┘                  └─
st   ───────────────────┘└──────────────────────┘
1774  
src  
typ  
doc  
txt  
par  
pid  
st   
1775  lemma sup_le {a : α} : (∀b ∈ s, f b ≤ a) → s.sup f ≤ a :=
id                                       └──┘   
src                                             └──┘   
typ                                      └──┘   
doc                                              └──┘
1776  by letI := classical.dec_eq β; from
id              └──────────────┘ 
src     └──────┘└──────────────┘   └───┘
typ     └──────┘└──────────────┘  └───┘
doc     └──────┘                   └───┘
txt     └──────┘                   └───┘
par     └──────┘                   └───┘
pid         └─┘                   └───┘
st     └─────────────────────────────────
1777  finset.induction_on s (λ _, bot_le) (λ n s hns ih H,
id   └─────────────────┘        └────┘
src  └─────────────────┘   └──┘└────┘└┘  └──────────────
typ  └─────────────────┘  └──┘└────┘└┘  └──────────────
doc  └─────────────────┘   └──┘      └┘  └──────────────
txt                        └──┘      └┘  └──────────────
par                        └──┘      └┘  └──────────────
pid                        └──┘      └┘  └──────────────
st   ─────────────────────────────────────────────────────
1778    by simp only [mem_insert, or_imp_distrib, forall_and_distrib, forall_eq] at H;
id                   └────────┘  └────────────┘  └────────────────┘  └───────┘
src  ─┘  └─────────┘└────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└────┘└─
typ  ─┘  └─────────┘└────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└────┘└─
doc  ─┘  └─────────┘          └┘              └┘                  └┘         └────┘└─
txt  ─┘  └─────────┘          └┘              └┘                  └┘         └────┘└─
par  ─┘  └─────────┘          └┘              └┘                  └┘         └────┘└─
pid  ─┘  └──────────┘          └┘              └┘                  └┘         └───────
st   ───┘└────────────────────────────────────────────────────────────────────────────
1779       simp only [sup_insert]; exact sup_le H.1 (ih H.2))
id                   └────────┘         └────┘      └┘ 
src  ────┘└─────────┘└────────┘└┘└────┘└────┘ └─┘    └─┘└─
typ  ────┘└─────────┘└────────┘└──────┘└────┘ └─┘ └┘└────
doc  ────┘└─────────┘          └┘└────┘       └─┘    └─┘└─
txt  ────┘└─────────┘          └┘└────┘       └─┘    └─┘└─
par  ────┘└─────────┘          └──────┘       └─┘    └────
pid  ───────────────┘          └───────┘       └─┘    └──┘
st   ─────────────────────────────────────────────────────┘└─
1780  
src  
typ  
doc  
txt  
par  
pid  
st   
1781  @[simp] lemma sup_le_iff {a : α} : s.sup f ≤ a ↔ (∀b ∈ s, f b ≤ a) :=
id                                     └──┘               
src                                      └──┘                    
typ                                    └──┘               
doc    └──┘                              └──┘
1782  iff.intro (assume h b hb, le_trans (le_sup hb) h) sup_le
id   └───────┘           └┘  └──────┘  └────┘ └┘    └────┘
src  └───────┘                 └──────┘  └────┘        └────┘
typ  └───────┘           └┘  └──────┘  └────┘ └┘    └────┘
1783  
1784  lemma sup_mono (h : s₁ ⊆ s₂) : s₁.sup f ≤ s₂.sup f :=
id                       └┘  └┘    └┘└──┘   └┘└──┘ 
src                                  └──┘      └──┘
typ                      └┘  └┘    └┘└──┘   └┘└──┘ 
doc                                   └──┘       └──┘
1785  sup_le $ assume b hb, le_sup (h hb)
id   └────┘           └┘  └────┘   └┘
src  └────┘                └────┘
typ  └────┘           └┘  └────┘   └┘
1786  
1787  @[simp] lemma sup_lt_iff [is_total α (≤)] {a : α} (ha : ⊥ < a) :
id                             └──────┘                     
src                            └──────┘                      
typ                            └──────┘                     
doc    └──┘
1788    s.sup f < a ↔ (∀b ∈ s, f b < a) :=
id     └──┘               
src     └──┘                    
typ    └──┘               
doc     └──┘
1789  by letI := classical.dec_eq β; from
id              └──────────────┘ 
src     └──────┘└──────────────┘   └───┘
typ     └──────┘└──────────────┘  └───┘
doc     └──────┘                   └───┘
txt     └──────┘                   └───┘
par     └──────┘                   └───┘
pid         └─┘                   └───┘
st     └─────────────────────────────────
1790  ⟨ λh b hb, lt_of_le_of_lt (le_sup hb) h,
id              └────────────┘  └────┘
src    └──────┘└────────────┘ └────┘  └┘ └─
typ    └──────┘└────────────┘ └────┘  └┘ └─
doc    └──────┘                       └┘ └─
txt    └──────┘                       └┘ └─
par    └──────┘                       └┘ └─
pid    └──────┘                       └┘ └─
st   ─────────────────────────────────────────
1791    finset.induction_on s (by simp [ha]) (by simp {contextual := tt}) ⟩
id     └─────────────────┘            └┘                           └┘
src  ─┘└─────────────────┘    └────┘  └┘   └───┘ └────────────┘└┘└───
typ  ─┘└─────────────────┘   └────┘└┘└┘   └───┘ └────────────┘└┘└───
doc  ─┘└─────────────────┘    └────┘  └┘   └───┘ └────────────┘  └───
txt  ─┘                       └────┘  └┘   └───┘ └────────────┘  └───
par  ─┘                       └────┘  └┘   └───┘ └────────────┘  └───
pid  ─┘                       └─────┘  └─┘   └────┘ └────────────┘  └──┘
st   ──────────────────────────┘└────────┘└───┘└──────────────────────┘└───
1792  
src  
typ  
doc  
txt  
par  
pid  
st   
1793  lemma comp_sup_eq_sup_comp [is_total α (≤)] {γ : Type} [semilattice_sup_bot γ]
id                               └──────┘                  └─────────────────┘ 
src                              └──────┘                   └─────────────────┘
typ                              └──────┘                  └─────────────────┘ 
doc                                                          └─────────────────┘
1794    (g : α → γ) (mono_g : monotone g) (bot : g ⊥ = ⊥) : g (s.sup f) = s.sup (g ∘ f) :=
id                         └──────┘                   └──┘    └──┘    
src                          └──────┘                       └──┘      └──┘    
typ                        └──────┘                   └──┘    └──┘    
doc                          └──────┘                          └──┘       └──┘
1795  have A : ∀x y, g (x ⊔ y) = g x ⊔ g y :=
id                           
src                               
typ                          
1796  begin
st   └─────
1797    assume x y,
src    └────────┘
typ    └────────┘
doc    └────────┘
txt    └────────┘
par    └────────┘
pid    └────────┘
st   ───────────┘└─
1798    cases (is_total.total (≤) x y) with h,
id            └────────────┘     
src    └────┘ └────────────┘└─┘  └──────┘
typ    └────┘ └────────────┘└─┘└──────┘
doc    └────┘                └─┘  └──────┘
txt    └────┘                └─┘  └──────┘
par    └────┘                └─┘  └──────┘
pid                         └─┘  └─────┘
st   ──────────────────────────────────────┘└─
1799    { simp [sup_of_le_right h, sup_of_le_right (mono_g h)] },
id             └─────────────┘   └─────────────┘  └────┘ 
src      └────┘└─────────────┘ └┘└─────────────┘        └─┘
typ      └────┘└─────────────┘└┘└─────────────┘ └────┘└─┘
doc      └────┘                └┘                       └─┘
txt      └────┘                └┘                       └─┘
par      └────┘                └┘                       └─┘
pid                          └┘                       └┘
st   ───┘└───────────────────────────────────────────────────┘└┘
1800    { simp [sup_of_le_left h, sup_of_le_left (mono_g h)] }
id             └────────────┘   └────────────┘  └────┘ 
src      └────┘└────────────┘ └┘└────────────┘        └─┘
typ      └────┘└────────────┘└┘└────────────┘ └────┘└─┘
doc      └────┘               └┘                      └─┘
txt      └────┘               └┘                      └─┘
par      └────┘               └┘                      └─┘
pid                         └┘                      └┘
st   ──────────────────────────────────────────────────────┘└─
1801  end,
st   ──┘
1802  by letI := classical.dec_eq β; from
id              └──────────────┘ 
src     └──────┘└──────────────┘   └───┘
typ     └──────┘└──────────────┘  └───┘
doc     └──────┘                   └───┘
txt     └──────┘                   └───┘
par     └──────┘                   └───┘
pid         └─┘                   └───┘
st     └─────────────────────────────────
1803  finset.induction_on s (by simp [bot]) (by simp [A] {contextual := tt})
id   └─────────────────┘            └─┘                              └┘
src  └─────────────────┘    └────┘   └┘   └────┘ └┘ └────────────┘└┘└─
typ  └─────────────────┘   └────┘└─┘└┘   └────┘└┘ └────────────┘└┘└─
doc  └─────────────────┘    └────┘   └┘   └────┘ └┘ └────────────┘  └─
txt                         └────┘   └┘   └────┘ └┘ └────────────┘  └─
par                         └────┘   └┘   └────┘ └┘ └────────────┘  └─
pid                         └─────┘   └─┘   └─────┘ └┘ └────────────┘  └┘
st   ────────────────────────┘└─────────┘└───┘└──────────────────────────┘└─
1804  
src  
typ  
doc  
txt  
par  
pid  
st   
1805  theorem subset_range_sup_succ (s : finset ℕ) : s ⊆ range (s.sup id).succ :=
id                                      └────┘       └───┘  └──┘ └┘ └──┘
src                                     └────┘        └───┘   └──┘ └┘ └──┘
typ                                     └────┘       └───┘  └──┘ └┘ └──┘
doc                                     └────┘          └───┘   └──┘
1806  λ n hn, mem_range.2 $ nat.lt_succ_of_le $ le_sup hn
id      └┘  └───────┘    └───────────────┘   └────┘ └┘
src          └───────┘    └───────────────┘   └────┘
typ     └┘  └───────┘    └───────────────┘   └────┘ └┘
1807  
1808  theorem exists_nat_subset_range (s : finset ℕ) : ∃n : ℕ, s ⊆ range n :=
id                                        └────┘            └───┘ 
src                                       └────┘             └───┘
typ                                       └────┘            └───┘ 
doc                                       └────┘                  └───┘
1809  ⟨_, s.subset_range_sup_succ⟩
id       └────────────────────┘
src       └────────────────────┘
typ      └────────────────────┘
1810  
1811  end sup
1812  
1813  lemma sup_eq_supr [complete_lattice β] (s : finset α) (f : α → β) : s.sup f = (⨆a∈s, f a) :=
id                      └──────────────┘        └────┘               └──┘       
src                     └──────────────┘         └────┘                   └──┘        
typ                     └──────────────┘        └────┘               └──┘       
doc                     └──────────────┘         └────┘                   └──┘         
1814  le_antisymm
id   └─────────┘
src  └─────────┘
typ  └─────────┘
1815    (finset.sup_le $ assume a ha, le_supr_of_le a $ le_supr _ ha)
id      └───────────┘           └┘  └───────────┘    └─────┘   └┘
src     └───────────┘                └───────────┘     └─────┘
typ     └───────────┘           └┘  └───────────┘    └─────┘   └┘
1816    (supr_le $ assume a, supr_le $ assume ha, le_sup ha)
id      └─────┘            └─────┘          └┘  └────┘ └┘
src     └─────┘             └─────┘              └────┘
typ     └─────┘            └─────┘          └┘  └────┘ └┘
1817  
1818  /-! ### inf -/
1819  section inf
1820  variables [semilattice_inf_top α]
id              └─────────────────┘
src             └─────────────────┘
typ             └─────────────────┘
doc             └─────────────────┘
1821  
1822  /-- Infimum of a finite set: `inf {a, b, c} f = f a ⊓ f b ⊓ f c` -/
1823  def inf (s : finset β) (f : β → α) : α := s.fold (⊓) ⊤ f
id                └────┘                   └───┘     
src               └────┘                        └───┘    
typ               └────┘                   └───┘     
doc               └────┘                        └───┘
1824  
1825  variables {s s₁ s₂ : finset β} {f : β → α}
id                        └────┘
src                       └────┘
typ                       └────┘
doc                       └────┘
1826  
1827  lemma inf_val : s.inf f = (s.1.map f).inf := rfl
id                   └──┘     └─┘   └─┘     └─┘
src                   └──┘       └─┘    └─┘     └─┘
typ                  └──┘     └─┘   └─┘     └─┘
doc                   └──┘         └─┘    └─┘
1828  
1829  @[simp] lemma inf_empty : (∅ : finset β).inf f = ⊤ :=
id                                 └────┘  └─┘    
src                                └────┘   └─┘     
typ                                └────┘  └─┘    
doc    └──┘                         └────┘   └─┘
1830  fold_empty
id   └────────┘
src  └────────┘
typ  └────────┘
1831  
1832  @[simp] lemma inf_insert [decidable_eq β] {b : β} : (insert b s : finset β).inf f = f b ⊓ s.inf f :=
id                             └──────────┘             └────┘     └────┘  └─┘       └──┘ 
src                            └──────────┘               └────┘       └────┘   └─┘           └──┘
typ                            └──────────┘             └────┘     └────┘  └─┘       └──┘ 
doc    └──┘                                                            └────┘   └─┘             └──┘
1833  fold_insert_idem
id   └──────────────┘
src  └──────────────┘
typ  └──────────────┘
1834  
1835  @[simp] lemma inf_singleton [decidable_eq β] {b : β} : ({b} : finset β).inf f = f b :=
id                                └──────────┘                 └────┘  └─┘     
src                               └──────────┘                    └────┘   └─┘    
typ                               └──────────┘                 └────┘  └─┘     
doc    └──┘                                                        └────┘   └─┘
1836  calc _ = f b ⊓ (∅:finset β).inf f : inf_insert
id                 └────┘  └─┘     └────────┘
src                  └────┘   └─┘      └────────┘
typ                └────┘  └─┘     └────────┘
doc                    └────┘   └─┘
1837    ... = f b : inf_top_eq
id               └────────┘
src                └────────┘
typ              └────────┘
1838  
1839  lemma inf_union [decidable_eq β] : (s₁ ∪ s₂).inf f = s₁.inf f ⊓ s₂.inf f :=
id                    └──────────┘      └┘  └┘ └─┘    └┘└──┘   └┘└──┘ 
src                   └──────────┘              └─┘       └──┘      └──┘
typ                   └──────────┘      └┘  └┘ └─┘    └┘└──┘   └┘└──┘ 
doc                                              └─┘        └──┘       └──┘
1840  finset.induction_on s₁ (by rw [empty_union, inf_empty, top_inf_eq]) $ λ a s has ih,
id   └─────────────────┘ └┘         └─────────┘  └───────┘  └────────┘         └─┘ └┘
src  └─────────────────┘        └──┘└─────────┘└┘└───────┘└┘└────────┘
typ  └─────────────────┘ └┘     └──┘└─────────┘└┘└───────┘└┘└────────┘        └─┘ └┘
doc  └─────────────────┘        └──┘           └┘         └┘          
txt                             └──┘           └┘         └┘          
par                             └──┘           └┘         └┘          
pid                               └┘           └┘         └┘          
st                             └──────────────┘└─────────┘└──────────┘
1841  by rw [insert_union, inf_insert, inf_insert, ih, inf_assoc]
id          └──────────┘  └────────┘  └────────┘  └┘  └───────┘
src     └──┘└──────────┘└┘└────────┘└┘└────────┘└┘  └┘└───────┘└─
typ     └──┘└──────────┘└┘└────────┘└┘└────────┘└┘└┘└┘└───────┘└─
doc     └──┘            └┘          └┘          └┘  └┘         └─
txt     └──┘            └┘          └┘          └┘  └┘         └─
par     └──┘            └┘          └┘          └┘  └┘         └─
pid       └┘            └┘          └┘          └┘  └┘         
st     └───────────────┘└──────────┘└──────────┘└──┘└─────────┘
1842  
src  
typ  
doc  
txt  
par  
pid  
st   
1843  theorem inf_congr {f g : β → α} (hs : s₁ = s₂) (hfg : ∀a∈s₂, f a = g a) : s₁.inf f = s₂.inf g :=
id                                       └┘  └┘           └┘          └┘└──┘   └┘└──┘ 
src                                                                            └──┘      └──┘
typ                                      └┘  └┘           └┘          └┘└──┘   └┘└──┘ 
doc                                                                              └──┘       └──┘
1844  by subst hs; exact finset.fold_congr hfg
id            └┘        └───────────────┘ └─┘
src     └────┘    └────┘└───────────────┘   
typ     └────┘└┘  └────┘└───────────────┘└─┘
doc     └────┘    └────┘                    
txt     └────┘    └────┘                    
par     └────┘    └────┘                    
pid                                       
st     └──────────────────────────────────────
1845  
src  
typ  
doc  
txt  
par  
pid  
st   
1846  lemma inf_mono_fun {g : β → α} : (∀b∈s, f b ≤ g b) → s.inf f ≤ s.inf g :=
id                                               └──┘   └──┘ 
src                                                       └──┘     └──┘
typ                                              └──┘   └──┘ 
doc                                                        └──┘      └──┘
1847  by letI := classical.dec_eq β; from
id              └──────────────┘ 
src     └──────┘└──────────────┘   └───┘
typ     └──────┘└──────────────┘  └───┘
doc     └──────┘                   └───┘
txt     └──────┘                   └───┘
par     └──────┘                   └───┘
pid         └─┘                   └───┘
st     └─────────────────────────────────
1848  finset.induction_on s (λ _, le_refl _) (λ a s has ih H,
id   └─────────────────┘        └─────┘
src  └─────────────────┘   └──┘└─────┘└──┘  └──────────────
typ  └─────────────────┘  └──┘└─────┘└──┘  └──────────────
doc  └─────────────────┘   └──┘       └──┘  └──────────────
txt                        └──┘       └──┘  └──────────────
par                        └──┘       └──┘  └──────────────
pid                        └──┘       └──┘  └──────────────
st   ────────────────────────────────────────────────────────
1849    by simp only [mem_insert, or_imp_distrib, forall_and_distrib, forall_eq] at H;
id                   └────────┘  └────────────┘  └────────────────┘  └───────┘
src  ─┘  └─────────┘└────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└────┘└─
typ  ─┘  └─────────┘└────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└────┘└─
doc  ─┘  └─────────┘          └┘              └┘                  └┘         └────┘└─
txt  ─┘  └─────────┘          └┘              └┘                  └┘         └────┘└─
par  ─┘  └─────────┘          └┘              └┘                  └┘         └────┘└─
pid  ─┘  └──────────┘          └┘              └┘                  └┘         └───────
st   ───┘└────────────────────────────────────────────────────────────────────────────
1850       simp only [inf_insert]; exact inf_le_inf H.1 (ih H.2))
id                   └────────┘         └────────┘      └┘ 
src  ────┘└─────────┘└────────┘└┘└────┘└────────┘ └─┘    └─┘└─
typ  ────┘└─────────┘└────────┘└──────┘└────────┘ └─┘ └┘└────
doc  ────┘└─────────┘          └┘└────┘           └─┘    └─┘└─
txt  ────┘└─────────┘          └┘└────┘           └─┘    └─┘└─
par  ────┘└─────────┘          └──────┘           └─┘    └────
pid  ───────────────┘          └───────┘           └─┘    └──┘
st   ─────────────────────────────────────────────────────────┘└─
1851  
src  
typ  
doc  
txt  
par  
pid  
st   
1852  lemma inf_le {b : β} (hb : b ∈ s) : s.inf f ≤ f b :=
id                                   └──┘    
src                                      └──┘   
typ                                  └──┘    
doc                                       └──┘
1853  by letI := classical.dec_eq β; from
id              └──────────────┘ 
src     └──────┘└──────────────┘   └───┘
typ     └──────┘└──────────────┘  └───┘
doc     └──────┘                   └───┘
txt     └──────┘                   └───┘
par     └──────┘                   └───┘
pid         └─┘                   └───┘
st     └─────────────────────────────────
1854  calc f b ≥ f b ⊓ s.inf f : inf_le_left
id                  └───┘    └─────────┘
src           └───┘ └─┘└─────────┘
typ          └───┘└─┘└─────────┘
doc            └───┘ └─┘           
txt                  └─┘           
par                  └─┘           
pid                  └─┘           
st   ───────────────────────────────────────
1855    ... = (insert b s).inf f : inf_insert.symm
id            └────┘              └─────────────┘
src  ─────┘  └────┘  └────┘ └─┘└─────────────┘
typ  ─────┘  └────┘  └────┘ └─┘└─────────────┘
doc  ─────┘          └────┘ └─┘               
txt  ─────┘          └────┘ └─┘               
par  ─────┘          └────┘ └─┘               
pid  ─────┘          └────┘ └─┘               
st   ─────────────────────────────────────────────
1856    ... = s.inf f : by rw [insert_eq_of_mem hb]
id                            └──────────────┘ └┘
src  ─────┘       └─┘  └──┘└──────────────┘  └─
typ  ─────┘       └─┘  └──┘└──────────────┘└┘└─
doc  ─────┘       └─┘  └──┘                  └─
txt  ─────┘       └─┘  └──┘                  └─
par  ─────┘       └─┘  └──┘                  └─
pid  ─────┘       └─┘  └───┘                  └─
st   ───────────────────┘└──────────────────────┘
1857  
src  
typ  
doc  
txt  
par  
pid  
st   
1858  lemma le_inf {a : α} : (∀b ∈ s, a ≤ f b) → a ≤ s.inf f :=
id                                         └──┘ 
src                                                └──┘
typ                                        └──┘ 
doc                                                  └──┘
1859  by letI := classical.dec_eq β; from
id              └──────────────┘ 
src     └──────┘└──────────────┘   └───┘
typ     └──────┘└──────────────┘  └───┘
doc     └──────┘                   └───┘
txt     └──────┘                   └───┘
par     └──────┘                   └───┘
pid         └─┘                   └───┘
st     └─────────────────────────────────
1860  finset.induction_on s (λ _, le_top) (λ n s hns ih H,
id   └─────────────────┘        └────┘
src  └─────────────────┘   └──┘└────┘└┘  └──────────────
typ  └─────────────────┘  └──┘└────┘└┘  └──────────────
doc  └─────────────────┘   └──┘      └┘  └──────────────
txt                        └──┘      └┘  └──────────────
par                        └──┘      └┘  └──────────────
pid                        └──┘      └┘  └──────────────
st   ─────────────────────────────────────────────────────
1861    by simp only [mem_insert, or_imp_distrib, forall_and_distrib, forall_eq] at H;
id                   └────────┘  └────────────┘  └────────────────┘  └───────┘
src  ─┘  └─────────┘└────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└────┘└─
typ  ─┘  └─────────┘└────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└────┘└─
doc  ─┘  └─────────┘          └┘              └┘                  └┘         └────┘└─
txt  ─┘  └─────────┘          └┘              └┘                  └┘         └────┘└─
par  ─┘  └─────────┘          └┘              └┘                  └┘         └────┘└─
pid  ─┘  └──────────┘          └┘              └┘                  └┘         └───────
st   ───┘└────────────────────────────────────────────────────────────────────────────
1862       simp only [inf_insert]; exact le_inf H.1 (ih H.2))
id                   └────────┘         └────┘      └┘ 
src  ────┘└─────────┘└────────┘└┘└────┘└────┘ └─┘    └─┘└─
typ  ────┘└─────────┘└────────┘└──────┘└────┘ └─┘ └┘└────
doc  ────┘└─────────┘          └┘└────┘       └─┘    └─┘└─
txt  ────┘└─────────┘          └┘└────┘       └─┘    └─┘└─
par  ────┘└─────────┘          └──────┘       └─┘    └────
pid  ───────────────┘          └───────┘       └─┘    └──┘
st   ─────────────────────────────────────────────────────┘└─
1863  
src  
typ  
doc  
txt  
par  
pid  
st   
1864  lemma le_inf_iff {a : α} : a ≤ s.inf f ↔ (∀b ∈ s, a ≤ f b) :=
id                               └──┘             
src                                 └──┘               
typ                              └──┘             
doc                                  └──┘
1865  iff.intro (assume h b hb, le_trans h (inf_le hb)) le_inf
id   └───────┘           └┘  └──────┘   └────┘ └┘   └────┘
src  └───────┘                 └──────┘    └────┘      └────┘
typ  └───────┘           └┘  └──────┘   └────┘ └┘   └────┘
1866  
1867  lemma inf_mono (h : s₁ ⊆ s₂) : s₂.inf f ≤ s₁.inf f :=
id                       └┘  └┘    └┘└──┘   └┘└──┘ 
src                                  └──┘      └──┘
typ                      └┘  └┘    └┘└──┘   └┘└──┘ 
doc                                   └──┘       └──┘
1868  le_inf $ assume b hb, inf_le (h hb)
id   └────┘           └┘  └────┘   └┘
src  └────┘                └────┘
typ  └────┘           └┘  └────┘   └┘
1869  
1870  lemma lt_inf [is_total α (≤)] {a : α} : (a < ⊤) → (∀b ∈ s, a < f b) → a < s.inf f :=
id                 └──────┘                                      └──┘ 
src                └──────┘                                                └──┘
typ                └──────┘                                      └──┘ 
doc                                                                             └──┘
1871  by letI := classical.dec_eq β; from
id              └──────────────┘ 
src     └──────┘└──────────────┘   └───┘
typ     └──────┘└──────────────┘  └───┘
doc     └──────┘                   └───┘
txt     └──────┘                   └───┘
par     └──────┘                   └───┘
pid         └─┘                   └───┘
st     └─────────────────────────────────
1872  finset.induction_on s (by simp) (by simp {contextual := tt})
id   └─────────────────┘                                    └┘
src  └─────────────────┘    └──┘└┘   └───┘ └────────────┘└┘└─
typ  └─────────────────┘   └──┘└┘   └───┘ └────────────┘└┘└─
doc  └─────────────────┘    └──┘└┘   └───┘ └────────────┘  └─
txt                         └──┘└┘   └───┘ └────────────┘  └─
par                         └──┘└┘   └───┘ └────────────┘  └─
pid                         └─────┘   └────┘ └────────────┘  └┘
st   ────────────────────────┘└───┘└───┘└──────────────────────┘└─
1873  
src  
typ  
doc  
txt  
par  
pid  
st   
1874  lemma comp_inf_eq_inf_comp [is_total α (≤)] {γ : Type} [semilattice_inf_top γ]
id                               └──────┘                  └─────────────────┘ 
src                              └──────┘                   └─────────────────┘
typ                              └──────┘                  └─────────────────┘ 
doc                                                          └─────────────────┘
1875    (g : α → γ) (mono_g : monotone g) (top : g ⊤ = ⊤) : g (s.inf f) = s.inf (g ∘ f) :=
id                         └──────┘                   └──┘    └──┘    
src                          └──────┘                       └──┘      └──┘    
typ                        └──────┘                   └──┘    └──┘    
doc                          └──────┘                          └──┘       └──┘
1876  have A : ∀x y, g (x ⊓ y) = g x ⊓ g y :=
id                           
src                               
typ                          
1877  begin
st   └─────
1878    assume x y,
src    └────────┘
typ    └────────┘
doc    └────────┘
txt    └────────┘
par    └────────┘
pid    └────────┘
st   ───────────┘└─
1879    cases (is_total.total (≤) x y) with h,
id            └────────────┘     
src    └────┘ └────────────┘└─┘  └──────┘
typ    └────┘ └────────────┘└─┘└──────┘
doc    └────┘                └─┘  └──────┘
txt    └────┘                └─┘  └──────┘
par    └────┘                └─┘  └──────┘
pid                         └─┘  └─────┘
st   ──────────────────────────────────────┘└─
1880    { simp [inf_of_le_left h, inf_of_le_left (mono_g h)] },
id             └────────────┘   └────────────┘  └────┘ 
src      └────┘└────────────┘ └┘└────────────┘        └─┘
typ      └────┘└────────────┘└┘└────────────┘ └────┘└─┘
doc      └────┘               └┘                      └─┘
txt      └────┘               └┘                      └─┘
par      └────┘               └┘                      └─┘
pid                         └┘                      └┘
st   ───┘└─────────────────────────────────────────────────┘└┘
1881    { simp [inf_of_le_right h, inf_of_le_right (mono_g h)] }
id             └─────────────┘   └─────────────┘  └────┘ 
src      └────┘└─────────────┘ └┘└─────────────┘        └─┘
typ      └────┘└─────────────┘└┘└─────────────┘ └────┘└─┘
doc      └────┘                └┘                       └─┘
txt      └────┘                └┘                       └─┘
par      └────┘                └┘                       └─┘
pid                          └┘                       └┘
st   ────────────────────────────────────────────────────────┘└─
1882  end,
st   ──┘
1883  by letI := classical.dec_eq β; from
id              └──────────────┘ 
src     └──────┘└──────────────┘   └───┘
typ     └──────┘└──────────────┘  └───┘
doc     └──────┘                   └───┘
txt     └──────┘                   └───┘
par     └──────┘                   └───┘
pid         └─┘                   └───┘
st     └─────────────────────────────────
1884  finset.induction_on s (by simp [top]) (by simp [A] {contextual := tt})
id   └─────────────────┘            └─┘                              └┘
src  └─────────────────┘    └────┘   └┘   └────┘ └┘ └────────────┘└┘└─
typ  └─────────────────┘   └────┘└─┘└┘   └────┘└┘ └────────────┘└┘└─
doc  └─────────────────┘    └────┘   └┘   └────┘ └┘ └────────────┘  └─
txt                         └────┘   └┘   └────┘ └┘ └────────────┘  └─
par                         └────┘   └┘   └────┘ └┘ └────────────┘  └─
pid                         └─────┘   └─┘   └─────┘ └┘ └────────────┘  └┘
st   ────────────────────────┘└─────────┘└───┘└──────────────────────────┘└─
1885  
src  
typ  
doc  
txt  
par  
pid  
st   
1886  end inf
1887  
1888  lemma inf_eq_infi [complete_lattice β] (s : finset α) (f : α → β) : s.inf f = (⨅a∈s, f a) :=
id                      └──────────────┘        └────┘               └──┘       
src                     └──────────────┘         └────┘                   └──┘        
typ                     └──────────────┘        └────┘               └──┘       
doc                     └──────────────┘         └────┘                   └──┘         
1889  le_antisymm
id   └─────────┘
src  └─────────┘
typ  └─────────┘
1890    (le_infi $ assume a, le_infi $ assume ha, inf_le ha)
id      └─────┘            └─────┘          └┘  └────┘ └┘
src     └─────┘             └─────┘              └────┘
typ     └─────┘            └─────┘          └┘  └────┘ └┘
1891    (finset.le_inf $ assume a ha, infi_le_of_le a $ infi_le _ ha)
id      └───────────┘           └┘  └───────────┘    └─────┘   └┘
src     └───────────┘                └───────────┘     └─────┘
typ     └───────────┘           └┘  └───────────┘    └─────┘   └┘
1892  
1893  /-! ### max and min of finite sets -/
1894  section max_min
1895  variables [decidable_linear_order α]
id              └────────────────────┘
src             └────────────────────┘
typ             └────────────────────┘
1896  
1897  protected def max : finset α → option α :=
id                       └────┘    └────┘ 
src                      └────┘     └────┘
typ                      └────┘    └────┘ 
doc                      └────┘
1898  fold (option.lift_or_get max) none some
id   └──┘  └────────────────┘ └─┘  └──┘ └──┘
src  └──┘  └────────────────┘ └─┘  └──┘ └──┘
typ  └──┘  └────────────────┘ └─┘  └──┘ └──┘
doc  └──┘
1899  
1900  theorem max_eq_sup_with_bot (s : finset α) :
id                                    └────┘ 
src                                   └────┘
typ                                   └────┘ 
doc                                   └────┘
1901    s.max = @sup (with_bot α) α _ s some := rfl
id     └──┘   └─┘  └──────┘       └──┘    └─┘
src     └──┘   └─┘  └──────┘          └──┘    └─┘
typ    └──┘   └─┘  └──────┘       └──┘    └─┘
doc             └─┘
1902  
1903  @[simp] theorem max_empty : (∅ : finset α).max = none := rfl
id                                   └────┘  └─┘   └──┘    └─┘
src                                  └────┘   └─┘   └──┘    └─┘
typ                                  └────┘  └─┘   └──┘    └─┘
doc    └──┘                           └────┘
1904  
1905  @[simp] theorem max_insert {a : α} {s : finset α} :
id                                          └────┘ 
src                                          └────┘
typ                                         └────┘ 
doc    └──┘                                  └────┘
1906    (insert a s).max = option.lift_or_get max (some a) s.max := fold_insert_idem
id      └────┘   └─┘   └────────────────┘ └─┘  └──┘   └──┘    └──────────────┘
src     └────┘     └─┘   └────────────────┘ └─┘  └──┘     └──┘    └──────────────┘
typ     └────┘   └─┘   └────────────────┘ └─┘  └──┘   └──┘    └──────────────┘
1907  
1908  @[simp] theorem max_singleton {a : α} : finset.max {a} = some a := max_insert
id                                          └────────┘    └──┘     └────────┘
src                                          └────────┘     └──┘      └────────┘
typ                                         └────────┘    └──┘     └────────┘
doc    └──┘
1909  
1910  @[simp] theorem max_singleton' {a : α} : finset.max (singleton a) = some a := max_singleton
id                                           └────────┘  └───────┘    └──┘     └───────────┘
src                                           └────────┘  └───────┘     └──┘      └───────────┘
typ                                          └────────┘  └───────┘    └──┘     └───────────┘
doc    └──┘                                               └───────┘
1911  
1912  theorem max_of_mem {s : finset α} {a : α} (h : a ∈ s) : ∃ b, b ∈ s.max :=
id                           └────┘                         └──┘
src                          └────┘                                └──┘
typ                          └────┘                         └──┘
doc                          └────┘
1913  (@le_sup (with_bot α) _ _ _ _ _ h _ rfl).imp $ λ b, Exists.fst
id     └────┘  └──────┘                └─┘ └─┘        └────────┘
src    └────┘  └──────┘                  └─┘ └─┘         └────────┘
typ    └────┘  └──────┘                └─┘ └─┘        └────────┘
1914  
1915  theorem max_of_nonempty {s : finset α} (h : s.nonempty) : ∃ a, a ∈ s.max :=
id                                └────┘        └───────┘        └──┘
src                               └────┘          └───────┘           └──┘
typ                               └────┘        └───────┘        └──┘
doc                               └────┘          └───────┘
1916  let ⟨a, ha⟩ := h in max_of_mem ha
id   └─┘     └┘         └────────┘
src                      └────────┘
typ  └─┘     └┘         └────────┘
1917  
1918  theorem max_eq_none {s : finset α} : s.max = none ↔ s = ∅ :=
id                            └────┘     └──┘  └──┘    
src                           └────┘       └──┘  └──┘     
typ                           └────┘     └──┘  └──┘    
doc                           └────┘
1919  ⟨λ h, s.eq_empty_or_nonempty.elim id
id        └───────────────────┘└───┘ └┘
src         └───────────────────┘└───┘ └┘
typ       └───────────────────┘└───┘ └┘
1920    (λ H, let ⟨a, ha⟩ := max_of_nonempty H in by rw h at ha; cases ha),
id          └─┘            └─────────────┘                         └┘
src                         └─────────────┘         └─┘ └────┘  └────┘
typ         └─┘            └─────────────┘        └─┘└────┘  └────┘└┘
doc                                                 └─┘ └────┘  └────┘
txt                                                 └─┘ └────┘  └────┘
par                                                 └─┘ └────┘  └────┘
pid                                                    └────┘       
st                                                 └───────────────────┘
1921    λ h, h.symm ▸ max_empty⟩
id         └───┘  └───────┘
src          └───┘  └───────┘
typ        └───┘  └───────┘
1922  
1923  theorem mem_of_max {s : finset α} : ∀ {a : α}, a ∈ s.max → a ∈ s :=
id                           └────┘                 └──┘     
src                          └────┘                     └──┘     
typ                          └────┘                 └──┘     
doc                          └────┘
1924  finset.induction_on s (λ _ H, by cases H)
id   └─────────────────┘                 
src  └─────────────────┘              └────┘
typ  └─────────────────┘           └────┘
doc  └─────────────────┘              └────┘
txt                                   └────┘
par                                   └────┘
pid                                        
st                                   └──────┘
1925    (λ b s _ (ih : ∀ {a}, a ∈ s.max → a ∈ s) a (h : a ∈ (insert b s).max),
id                        └──┘                └────┘   └─┘
src                              └──┘                    └────┘     └─┘
typ                       └──┘                └────┘   └─┘
1926    begin
st     └─────
1927      by_cases p : b = a,
id                      
src      └───────┘ └─┘ 
typ      └───────┘ └─┘
doc      └───────┘ └─┘  
txt      └───────┘ └─┘  
par      └───────┘ └─┘  
pid               └─┘  
st   ─────────────────────┘└─
1928      { induction p, exact mem_insert_self b s },
id                           └─────────────┘  
src        └────────┘   └────┘└─────────────┘  
typ        └────────┘  └────┘└─────────────┘
doc        └────────┘   └────┘                 
txt        └────────┘   └────┘                 
par        └────────┘   └────┘                 
pid                                          
st   ─────┘└─────────┘└──────────────────────────┘└┘
1929      { cases option.lift_or_get_choice max_choice (some b) s.max with q q;
id               └───────────────────────┘ └────────┘  └──┘   └───┘
src        └────┘└───────────────────────┘└────────┘ └──┘ └┘└───┘└───────┘
typ        └────┘└───────────────────────┘└────────┘ └──┘└┘└───┘└───────┘
doc        └────┘                                         └┘     └───────┘
txt        └────┘                                         └┘     └───────┘
par        └────┘                                         └┘     └───────┘
pid                                                      └┘     └───────┘
st   ──────────────────────────────────────────────────────────────────────────
1930        rw [max_insert, q] at h,
id             └────────┘  
src        └──┘└────────┘└┘ └────┘
typ        └──┘└────────┘└┘└────┘
doc        └──┘          └┘ └────┘
txt        └──┘          └┘ └────┘
par        └──┘          └┘ └────┘
pid          └┘          └┘ └───┘
st   ─────────┘└────────┘└─┘└───┘└─
1931        { cases h, cases p rfl },
id                          └─┘
src          └────┘   └────┘ └─┘
typ          └────┘  └────┘└─┘
doc          └────┘   └────┘    
txt          └────┘   └────┘    
par          └────┘   └────┘    
pid                           
st   ───────┘└─────┘└────────────┘└┘
1932        { exact mem_insert_of_mem (ih h) } }
id                 └───────────────┘  └┘ 
src          └────┘└───────────────┘    └┘
typ          └────┘└───────────────┘ └┘└┘
doc          └────┘                     └┘
txt          └────┘                     └┘
par          └────┘                     └┘
pid                                    
st   ──────────────────────────────────────┘└───
1933    end)
st   ────┘
1934  
1935  theorem le_max_of_mem {s : finset α} {a b : α} (h₁ : a ∈ s) (h₂ : b ∈ s.max) : a ≤ b :=
id                              └────┘                              └──┘      
src                             └────┘                                    └──┘      
typ                             └────┘                              └──┘      
doc                             └────┘
1936  by rcases @le_sup (with_bot α) _ _ _ _ _ h₁ _ rfl with ⟨b', hb, ab⟩;
id              └────┘  └──────┘             └┘   └─┘
src     └─────┘ └────┘ └──────┘ └──────────┘  └─┘└─┘└────────────────┘
typ     └─────┘ └────┘ └──────┘└──────────┘└┘└─┘└─┘└────────────────┘
doc     └─────┘                 └──────────┘  └─┘   └────────────────┘
txt     └─────┘                 └──────────┘  └─┘   └────────────────┘
par     └─────┘                 └──────────┘  └─┘   └────────────────┘
pid                            └──────────┘  └─┘   └────────────────┘
st     └──────────────────────────────────────────────────────────────────
1937     cases h₂.symm.trans hb; assumption
id            └───────────┘ └┘
src     └────┘└───────────┘    └──────────
typ     └────┘└───────────┘└┘  └──────────
doc     └────┘                 └──────────
txt     └────┘                 └──────────
par     └────┘                 └──────────
pid                                     
st   ──────────────────────────────────────
1938  
src  
typ  
doc  
txt  
par  
pid  
st   
1939  protected def min : finset α → option α :=
id                       └────┘    └────┘ 
src                      └────┘     └────┘
typ                      └────┘    └────┘ 
doc                      └────┘
1940  fold (option.lift_or_get min) none some
id   └──┘  └────────────────┘ └─┘  └──┘ └──┘
src  └──┘  └────────────────┘ └─┘  └──┘ └──┘
typ  └──┘  └────────────────┘ └─┘  └──┘ └──┘
doc  └──┘
1941  
1942  theorem min_eq_inf_with_top (s : finset α) :
id                                    └────┘ 
src                                   └────┘
typ                                   └────┘ 
doc                                   └────┘
1943    s.min = @inf (with_top α) α _ s some := rfl
id     └──┘   └─┘  └──────┘       └──┘    └─┘
src     └──┘   └─┘  └──────┘          └──┘    └─┘
typ    └──┘   └─┘  └──────┘       └──┘    └─┘
doc             └─┘
1944  
1945  @[simp] theorem min_empty : (∅ : finset α).min = none := rfl
id                                   └────┘  └─┘   └──┘    └─┘
src                                  └────┘   └─┘   └──┘    └─┘
typ                                  └────┘  └─┘   └──┘    └─┘
doc    └──┘                           └────┘
1946  
1947  @[simp] theorem min_insert {a : α} {s : finset α} :
id                                          └────┘ 
src                                          └────┘
typ                                         └────┘ 
doc    └──┘                                  └────┘
1948    (insert a s).min = option.lift_or_get min (some a) s.min :=
id      └────┘   └─┘   └────────────────┘ └─┘  └──┘   └──┘
src     └────┘     └─┘   └────────────────┘ └─┘  └──┘     └──┘
typ     └────┘   └─┘   └────────────────┘ └─┘  └──┘   └──┘
1949  fold_insert_idem
id   └──────────────┘
src  └──────────────┘
typ  └──────────────┘
1950  
1951  @[simp] theorem min_singleton {a : α} : finset.min {a} = some a := min_insert
id                                          └────────┘    └──┘     └────────┘
src                                          └────────┘     └──┘      └────────┘
typ                                         └────────┘    └──┘     └────────┘
doc    └──┘
1952  
1953  theorem min_of_mem {s : finset α} {a : α} (h : a ∈ s) : ∃ b, b ∈ s.min :=
id                           └────┘                         └──┘
src                          └────┘                                └──┘
typ                          └────┘                         └──┘
doc                          └────┘
1954  (@inf_le (with_top α) _ _ _ _ _ h _ rfl).imp $ λ b, Exists.fst
id     └────┘  └──────┘                └─┘ └─┘        └────────┘
src    └────┘  └──────┘                  └─┘ └─┘         └────────┘
typ    └────┘  └──────┘                └─┘ └─┘        └────────┘
1955  
1956  theorem min_of_nonempty {s : finset α} (h : s.nonempty) : ∃ a, a ∈ s.min :=
id                                └────┘        └───────┘        └──┘
src                               └────┘          └───────┘           └──┘
typ                               └────┘        └───────┘        └──┘
doc                               └────┘          └───────┘
1957  let ⟨a, ha⟩ := h in min_of_mem ha
id   └─┘     └┘         └────────┘
src                      └────────┘
typ  └─┘     └┘         └────────┘
1958  
1959  theorem min_eq_none {s : finset α} : s.min = none ↔ s = ∅ :=
id                            └────┘     └──┘  └──┘    
src                           └────┘       └──┘  └──┘     
typ                           └────┘     └──┘  └──┘    
doc                           └────┘
1960  ⟨λ h, s.eq_empty_or_nonempty.elim id
id        └───────────────────┘└───┘ └┘
src         └───────────────────┘└───┘ └┘
typ       └───────────────────┘└───┘ └┘
1961    (λ H, let ⟨a, ha⟩ := min_of_nonempty H in by rw h at ha; cases ha),
id          └─┘            └─────────────┘                         └┘
src                         └─────────────┘         └─┘ └────┘  └────┘
typ         └─┘            └─────────────┘        └─┘└────┘  └────┘└┘
doc                                                 └─┘ └────┘  └────┘
txt                                                 └─┘ └────┘  └────┘
par                                                 └─┘ └────┘  └────┘
pid                                                    └────┘       
st                                                 └───────────────────┘
1962    λ h, h.symm ▸ min_empty⟩
id         └───┘  └───────┘
src          └───┘  └───────┘
typ        └───┘  └───────┘
1963  
1964  theorem mem_of_min {s : finset α} : ∀ {a : α}, a ∈ s.min → a ∈ s :=
id                           └────┘                 └──┘     
src                          └────┘                     └──┘     
typ                          └────┘                 └──┘     
doc                          └────┘
1965  finset.induction_on s (λ _ H, by cases H) $
id   └─────────────────┘                 
src  └─────────────────┘              └────┘
typ  └─────────────────┘           └────┘
doc  └─────────────────┘              └────┘
txt                                   └────┘
par                                   └────┘
pid                                        
st                                   └──────┘
1966    λ b s _ (ih : ∀ {a}, a ∈ s.min → a ∈ s) a (h : a ∈ (insert b s).min),
id                       └──┘                └────┘   └─┘
src                             └──┘                    └────┘     └─┘
typ                      └──┘                └────┘   └─┘
1967    begin
st     └─────
1968      by_cases p : b = a,
id                      
src      └───────┘ └─┘ 
typ      └───────┘ └─┘
doc      └───────┘ └─┘  
txt      └───────┘ └─┘  
par      └───────┘ └─┘  
pid               └─┘  
st   ─────────────────────┘└─
1969      { induction p, exact mem_insert_self b s },
id                           └─────────────┘  
src        └────────┘   └────┘└─────────────┘  
typ        └────────┘  └────┘└─────────────┘
doc        └────────┘   └────┘                 
txt        └────────┘   └────┘                 
par        └────────┘   └────┘                 
pid                                          
st   ─────┘└─────────┘└──────────────────────────┘└┘
1970      { cases option.lift_or_get_choice min_choice (some b) s.min with q q;
id               └───────────────────────┘ └────────┘  └──┘   └───┘
src        └────┘└───────────────────────┘└────────┘ └──┘ └┘└───┘└───────┘
typ        └────┘└───────────────────────┘└────────┘ └──┘└┘└───┘└───────┘
doc        └────┘                                         └┘     └───────┘
txt        └────┘                                         └┘     └───────┘
par        └────┘                                         └┘     └───────┘
pid                                                      └┘     └───────┘
st   ──────────────────────────────────────────────────────────────────────────
1971        rw [min_insert, q] at h,
id             └────────┘  
src        └──┘└────────┘└┘ └────┘
typ        └──┘└────────┘└┘└────┘
doc        └──┘          └┘ └────┘
txt        └──┘          └┘ └────┘
par        └──┘          └┘ └────┘
pid          └┘          └┘ └───┘
st   ─────────┘└────────┘└─┘└───┘└─
1972        { cases h, cases p rfl },
id                          └─┘
src          └────┘   └────┘ └─┘
typ          └────┘  └────┘└─┘
doc          └────┘   └────┘    
txt          └────┘   └────┘    
par          └────┘   └────┘    
pid                           
st   ───────┘└─────┘└────────────┘└┘
1973        { exact mem_insert_of_mem (ih h) } }
id                 └───────────────┘  └┘ 
src          └────┘└───────────────┘    └┘
typ          └────┘└───────────────┘ └┘└┘
doc          └────┘                     └┘
txt          └────┘                     └┘
par          └────┘                     └┘
pid                                    
st   ──────────────────────────────────────┘└───
1974    end
st   ────┘
1975  
1976  theorem min_le_of_mem {s : finset α} {a b : α} (h₁ : b ∈ s) (h₂ : a ∈ s.min) : a ≤ b :=
id                              └────┘                              └──┘      
src                             └────┘                                    └──┘      
typ                             └────┘                              └──┘      
doc                             └────┘
1977  by rcases @inf_le (with_top α) _ _ _ _ _ h₁ _ rfl with ⟨b', hb, ab⟩;
id              └────┘  └──────┘             └┘   └─┘
src     └─────┘ └────┘ └──────┘ └──────────┘  └─┘└─┘└────────────────┘
typ     └─────┘ └────┘ └──────┘└──────────┘└┘└─┘└─┘└────────────────┘
doc     └─────┘                 └──────────┘  └─┘   └────────────────┘
txt     └─────┘                 └──────────┘  └─┘   └────────────────┘
par     └─────┘                 └──────────┘  └─┘   └────────────────┘
pid                            └──────────┘  └─┘   └────────────────┘
st     └──────────────────────────────────────────────────────────────────
1978     cases h₂.symm.trans hb; assumption
id            └───────────┘ └┘
src     └────┘└───────────┘    └──────────
typ     └────┘└───────────┘└┘  └──────────
doc     └────┘                 └──────────
txt     └────┘                 └──────────
par     └────┘                 └──────────
pid                                     
st   ──────────────────────────────────────
1979  
src  
typ  
doc  
txt  
par  
pid  
st   
1980  lemma exists_min (s : finset β) (f : β → α) (h : s.nonempty) : ∃ x ∈ s, ∀ x' ∈ s, f x ≤ f x' :=
id                         └────┘                  └───────┘           └┘         └┘
src                        └────┘                      └───────┘                         
typ                        └────┘                  └───────┘           └┘         └┘
doc                        └────┘                      └───────┘
1981  begin
st   └─────
1982    cases min_of_nonempty (h.image f) with y hy,
id           └─────────────┘  └─────┘ 
src    └────┘└─────────────┘ └─────┘ └─────────┘
typ    └────┘└─────────────┘ └─────┘└─────────┘
doc    └────┘                        └─────────┘
txt    └────┘                        └─────────┘
par    └────┘                        └─────────┘
pid                                 └────────┘
st   ────────────────────────────────────────────┘└─
1983    rcases mem_image.mp (mem_of_min hy) with ⟨x, hx, rfl⟩,
id            └──────────┘  └────────┘ └┘
src    └─────┘└──────────┘ └────────┘  └─────────────────┘
typ    └─────┘└──────────┘ └────────┘└┘└─────────────────┘
doc    └─────┘                         └─────────────────┘
txt    └─────┘                         └─────────────────┘
par    └─────┘                         └─────────────────┘
pid                                   └─────────────────┘
st   ──────────────────────────────────────────────────────┘└─
1984    exact ⟨x, hx, λ x' hx', min_le_of_mem (mem_image_of_mem f hx') hy⟩
id              └┘            └───────────┘  └──────────────┘       └┘
src    └────┘  └┘  └┘ └───────┘└───────────┘ └──────────────┘    └┘  └┘
typ    └────┘ └┘└┘└┘ └───────┘└───────────┘ └──────────────┘   └┘└┘└┘
doc    └────┘  └┘  └┘ └───────┘                                  └┘  └┘
txt    └────┘  └┘  └┘ └───────┘                                  └┘  └┘
par    └────┘  └┘  └┘ └───────┘                                  └┘  └┘
pid           └┘  └┘ └───────┘                                  └┘  
st   ────────────────────────────────────────────────────────────────────┘
1985  end
st   └─┘
1986  
1987  end max_min
1988  
1989  /-! ### sort -/
1990  section sort
1991  variables (r : α → α → Prop) [decidable_rel r]
id                                 └───────────┘
src                                └───────────┘
typ                                └───────────┘
1992    [is_trans α r] [is_antisymm α r] [is_total α r]
id      └──────┘       └─────────┘       └──────┘
src     └──────┘       └─────────┘       └──────┘
typ     └──────┘       └─────────┘       └──────┘
1993  
1994  /-- `sort s` constructs a sorted list from the unordered set `s`.
1995    (Uses merge sort algorithm.) -/
1996  def sort (s : finset α) : list α := sort r s.1
id                 └────┘     └──┘     └──┘  
src                └────┘      └──┘      └──┘    
typ                └────┘     └──┘     └──┘  
doc                └────┘                └──┘
1997  
1998  @[simp] theorem sort_sorted (s : finset α) : list.sorted r (sort r s) :=
id                                    └────┘     └─────────┘   └──┘  
src                                   └────┘      └─────────┘    └──┘
typ                                   └────┘     └─────────┘   └──┘  
doc    └──┘                           └────┘      └─────────┘    └──┘
1999  sort_sorted _ _
id   └─────────┘
src  └─────────┘
typ  └─────────┘
2000  
2001  @[simp] theorem sort_eq (s : finset α) : ↑(sort r s) = s.1 :=
id                                └────┘      └──┘     
src                               └────┘       └──┘        
typ                               └────┘      └──┘     
doc    └──┘                       └────┘        └──┘
2002  sort_eq _ _
id   └─────┘
src  └─────┘
typ  └─────┘
2003  
2004  @[simp] theorem sort_nodup (s : finset α) : (sort r s).nodup :=
id                                   └────┘      └──┘   └───┘
src                                  └────┘       └──┘     └───┘
typ                                  └────┘      └──┘   └───┘
doc    └──┘                          └────┘       └──┘     └───┘
2005  (by rw sort_eq; exact s.2 : @multiset.nodup α (sort r s))
id          └─────┘              └────────────┘   └──┘  
src      └─┘└─────┘  └────┘ └─┘   └────────────┘    └──┘
typ      └─┘└─────┘  └────┘└─┘   └────────────┘   └──┘  
doc      └─┘         └────┘ └─┘   └────────────┘    └──┘
txt      └─┘         └────┘ └─┘
par      └─┘         └────┘ └─┘
pid                       └─┘
st      └─────────────────────┘
2006  
2007  @[simp] theorem sort_to_finset [decidable_eq α] (s : finset α) : (sort r s).to_finset = s :=
id                                   └──────────┘        └────┘      └──┘   └───────┘   
src                                  └──────────┘         └────┘       └──┘     └───────┘  
typ                                  └──────────┘        └────┘      └──┘   └───────┘   
doc    └──┘                                               └────┘       └──┘     └───────┘
2008  list.to_finset_eq (sort_nodup r s) ▸ eq_of_veq (sort_eq r s)
id   └───────────────┘  └────────┘     └───────┘  └─────┘  
src  └───────────────┘  └────────┘       └───────┘  └─────┘
typ  └───────────────┘  └────────┘     └───────┘  └─────┘  
2009  
2010  @[simp] theorem mem_sort {s : finset α} {a : α} : a ∈ sort r s ↔ a ∈ s :=
id                                 └────┘              └──┘      
src                                └────┘                 └──┘        
typ                                └────┘              └──┘      
doc    └──┘                        └────┘                  └──┘
2011  multiset.mem_sort _
id   └───────────────┘
src  └───────────────┘
typ  └───────────────┘
2012  
2013  @[simp] theorem length_sort {s : finset α} : (sort r s).length = s.card :=
id                                    └────┘      └──┘   └────┘   └───┘
src                                   └────┘       └──┘     └────┘    └───┘
typ                                   └────┘      └──┘   └────┘   └───┘
doc    └──┘                           └────┘       └──┘                └───┘
2014  multiset.length_sort _
id   └──────────────────┘
src  └──────────────────┘
typ  └──────────────────┘
2015  
2016  end sort
2017  
2018  /-! ### disjoint -/
2019  section disjoint
2020  variable [decidable_eq α]
id             └──────────┘
src            └──────────┘
typ            └──────────┘
2021  
2022  theorem disjoint_left {s t : finset α} : disjoint s t ↔ ∀ {a}, a ∈ s → a ∉ t :=
id                                └────┘     └──────┘                 
src                               └────┘      └──────┘                      
typ                               └────┘     └──────┘                 
doc                               └────┘      └──────┘
2023  by simp only [_root_.disjoint, inf_eq_inter, le_iff_subset, subset_iff, mem_inter, not_and, and_imp]; refl
id                 └─────────────┘  └──────────┘  └───────────┘  └────────┘  └───────┘  └─────┘  └─────┘
src     └─────────┘└─────────────┘└┘└──────────┘└┘└───────────┘└┘└────────┘└┘└───────┘└┘└─────┘└┘└─────┘  └────
typ     └─────────┘└─────────────┘└┘└──────────┘└┘└───────────┘└┘└────────┘└┘└───────┘└┘└─────┘└┘└─────┘  └────
doc     └─────────┘└─────────────┘└┘            └┘             └┘          └┘         └┘       └┘         └────
txt     └─────────┘               └┘            └┘             └┘          └┘         └┘       └┘         └────
par     └─────────┘               └┘            └┘             └┘          └┘         └┘       └┘         └────
pid         └──┘└┘               └┘            └┘             └┘          └┘         └┘       └┘             
st     └────────────────────────────────────────────────────────────────────────────────────────────────────────
2024  
src  
typ  
doc  
txt  
par  
pid  
st   
2025  theorem disjoint_val {s t : finset α} : disjoint s t ↔ s.1.disjoint t.1 :=
id                               └────┘     └──────┘     └──────┘  
src                              └────┘      └──────┘        └──────┘   
typ                              └────┘     └──────┘     └──────┘  
doc                              └────┘      └──────┘          └──────┘
2026  disjoint_left
id   └───────────┘
src  └───────────┘
typ  └───────────┘
2027  
2028  theorem disjoint_iff_inter_eq_empty {s t : finset α} : disjoint s t ↔ s ∩ t = ∅ :=
id                                              └────┘     └──────┘        
src                                             └────┘      └──────┘            
typ                                             └────┘     └──────┘        
doc                                             └────┘      └──────┘
2029  disjoint_iff
id   └──────────┘
src  └──────────┘
typ  └──────────┘
2030  
2031  theorem disjoint_right {s t : finset α} : disjoint s t ↔ ∀ {a}, a ∈ t → a ∉ s :=
id                                 └────┘     └──────┘                 
src                                └────┘      └──────┘                      
typ                                └────┘     └──────┘                 
doc                                └────┘      └──────┘
2032  by rw [disjoint.comm, disjoint_left]
id          └───────────┘  └───────────┘
src     └──┘└───────────┘└┘└───────────┘└─
typ     └──┘└───────────┘└┘└───────────┘└─
doc     └──┘             └┘             └─
txt     └──┘             └┘             └─
par     └──┘             └┘             └─
pid       └┘             └┘             
st     └────────────────┘└─────────────┘
2033  
src  
typ  
doc  
txt  
par  
pid  
st   
2034  theorem disjoint_iff_ne {s t : finset α} : disjoint s t ↔ ∀ a ∈ s, ∀ b ∈ t, a ≠ b :=
id                                  └────┘     └──────┘                    
src                                 └────┘      └──────┘                          
typ                                 └────┘     └──────┘                    
doc                                 └────┘      └──────┘
2035  by simp only [disjoint_left, imp_not_comm, forall_eq']
id                 └───────────┘  └──────────┘  └────────┘
src     └─────────┘└───────────┘└┘└──────────┘└┘└────────┘└─
typ     └─────────┘└───────────┘└┘└──────────┘└┘└────────┘└─
doc     └─────────┘             └┘            └┘          └─
txt     └─────────┘             └┘            └┘          └─
par     └─────────┘             └┘            └┘          └─
pid         └──┘└┘             └┘            └┘          
st     └────────────────────────────────────────────────────
2036  
src  
typ  
doc  
txt  
par  
pid  
st   
2037  theorem disjoint_of_subset_left {s t u : finset α} (h : s ⊆ u) (d : disjoint u t) : disjoint s t :=
id                                            └────┘                 └──────┘      └──────┘  
src                                           └────┘                    └──────┘        └──────┘
typ                                           └────┘                 └──────┘      └──────┘  
doc                                           └────┘                     └──────┘        └──────┘
2038  disjoint_left.2 (λ x m₁, (disjoint_left.1 d) (h m₁))
id   └───────────┘      └┘   └───────────┘      └┘
src  └───────────┘            └───────────┘
typ  └───────────┘      └┘   └───────────┘      └┘
2039  
2040  theorem disjoint_of_subset_right {s t u : finset α} (h : t ⊆ u) (d : disjoint s u) : disjoint s t :=
id                                             └────┘                 └──────┘      └──────┘  
src                                            └────┘                    └──────┘        └──────┘
typ                                            └────┘                 └──────┘      └──────┘  
doc                                            └────┘                     └──────┘        └──────┘
2041  disjoint_right.2 (λ x m₁, (disjoint_right.1 d) (h m₁))
id   └────────────┘      └┘   └────────────┘      └┘
src  └────────────┘            └────────────┘
typ  └────────────┘      └┘   └────────────┘      └┘
2042  
2043  @[simp] theorem disjoint_empty_left (s : finset α) : disjoint ∅ s := disjoint_bot_left
id                                            └────┘     └──────┘      └───────────────┘
src                                           └────┘      └──────┘       └───────────────┘
typ                                           └────┘     └──────┘      └───────────────┘
doc    └──┘                                   └────┘      └──────┘
2044  
2045  @[simp] theorem disjoint_empty_right (s : finset α) : disjoint s ∅ := disjoint_bot_right
id                                             └────┘     └──────┘      └────────────────┘
src                                            └────┘      └──────┘       └────────────────┘
typ                                            └────┘     └──────┘      └────────────────┘
doc    └──┘                                    └────┘      └──────┘
2046  
2047  @[simp] theorem singleton_disjoint {s : finset α} {a : α} : disjoint (singleton a) s ↔ a ∉ s :=
id                                           └────┘            └──────┘  └───────┘       
src                                          └────┘              └──────┘  └───────┘         
typ                                          └────┘            └──────┘  └───────┘       
doc    └──┘                                  └────┘              └──────┘  └───────┘
2048  by simp only [disjoint_left, mem_singleton, forall_eq]
id                 └───────────┘  └───────────┘  └───────┘
src     └─────────┘└───────────┘└┘└───────────┘└┘└───────┘└─
typ     └─────────┘└───────────┘└┘└───────────┘└┘└───────┘└─
doc     └─────────┘             └┘             └┘         └─
txt     └─────────┘             └┘             └┘         └─
par     └─────────┘             └┘             └┘         └─
pid         └──┘└┘             └┘             └┘         
st     └────────────────────────────────────────────────────
2049  
src  
typ  
doc  
txt  
par  
pid  
st   
2050  @[simp] theorem disjoint_singleton {s : finset α} {a : α} : disjoint s (singleton a) ↔ a ∉ s :=
id                                           └────┘            └──────┘   └───────┘      
src                                          └────┘              └──────┘    └───────┘       
typ                                          └────┘            └──────┘   └───────┘      
doc    └──┘                                  └────┘              └──────┘    └───────┘
2051  disjoint.comm.trans singleton_disjoint
id   └───────────┘└────┘ └────────────────┘
src  └───────────┘└────┘ └────────────────┘
typ  └───────────┘└────┘ └────────────────┘
2052  
2053  @[simp] theorem disjoint_insert_left {a : α} {s t : finset α} :
id                                                      └────┘ 
src                                                      └────┘
typ                                                     └────┘ 
doc    └──┘                                              └────┘
2054    disjoint (insert a s) t ↔ a ∉ t ∧ disjoint s t :=
id     └──────┘  └────┘          └──────┘  
src    └──────┘  └────┘               └──────┘
typ    └──────┘  └────┘          └──────┘  
doc    └──────┘                          └──────┘
2055  by simp only [disjoint_left, mem_insert, or_imp_distrib, forall_and_distrib, forall_eq]
id                 └───────────┘  └────────┘  └────────────┘  └────────────────┘  └───────┘
src     └─────────┘└───────────┘└┘└────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└─
typ     └─────────┘└───────────┘└┘└────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└─
doc     └─────────┘             └┘          └┘              └┘                  └┘         └─
txt     └─────────┘             └┘          └┘              └┘                  └┘         └─
par     └─────────┘             └┘          └┘              └┘                  └┘         └─
pid         └──┘└┘             └┘          └┘              └┘                  └┘         
st     └─────────────────────────────────────────────────────────────────────────────────────
2056  
src  
typ  
doc  
txt  
par  
pid  
st   
2057  @[simp] theorem disjoint_insert_right {a : α} {s t : finset α} :
id                                                       └────┘ 
src                                                       └────┘
typ                                                      └────┘ 
doc    └──┘                                               └────┘
2058    disjoint s (insert a t) ↔ a ∉ s ∧ disjoint s t :=
id     └──────┘   └────┘         └──────┘  
src    └──────┘    └────┘             └──────┘
typ    └──────┘   └────┘         └──────┘  
doc    └──────┘                          └──────┘
2059  disjoint.comm.trans $ by rw [disjoint_insert_left, disjoint.comm]
id   └───────────┘└────┘          └──────────────────┘  └───────────┘
src  └───────────┘└────┘      └──┘└──────────────────┘└┘└───────────┘└─
typ  └───────────┘└────┘      └──┘└──────────────────┘└┘└───────────┘└─
doc                           └──┘                    └┘             └─
txt                           └──┘                    └┘             └─
par                           └──┘                    └┘             └─
pid                             └┘                    └┘             
st                           └───────────────────────┘└─────────────┘
2060  
src  
typ  
doc  
txt  
par  
pid  
st   
2061  @[simp] theorem disjoint_union_left {s t u : finset α} :
id                                                └────┘ 
src                                               └────┘
typ                                               └────┘ 
doc    └──┘                                       └────┘
2062    disjoint (s ∪ t) u ↔ disjoint s u ∧ disjoint t u :=
id     └──────┘        └──────┘    └──────┘  
src    └──────┘           └──────┘      └──────┘
typ    └──────┘        └──────┘    └──────┘  
doc    └──────┘             └──────┘       └──────┘
2063  by simp only [disjoint_left, mem_union, or_imp_distrib, forall_and_distrib]
id                 └───────────┘  └───────┘  └────────────┘  └────────────────┘
src     └─────────┘└───────────┘└┘└───────┘└┘└────────────┘└┘└────────────────┘└─
typ     └─────────┘└───────────┘└┘└───────┘└┘└────────────┘└┘└────────────────┘└─
doc     └─────────┘             └┘         └┘              └┘                  └─
txt     └─────────┘             └┘         └┘              └┘                  └─
par     └─────────┘             └┘         └┘              └┘                  └─
pid         └──┘└┘             └┘         └┘              └┘                  
st     └─────────────────────────────────────────────────────────────────────────
2064  
src  
typ  
doc  
txt  
par  
pid  
st   
2065  @[simp] theorem disjoint_union_right {s t u : finset α} :
id                                                 └────┘ 
src                                                └────┘
typ                                                └────┘ 
doc    └──┘                                        └────┘
2066    disjoint s (t ∪ u) ↔ disjoint s t ∧ disjoint s u :=
id     └──────┘        └──────┘    └──────┘  
src    └──────┘           └──────┘      └──────┘
typ    └──────┘        └──────┘    └──────┘  
doc    └──────┘             └──────┘       └──────┘
2067  by simp only [disjoint_right, mem_union, or_imp_distrib, forall_and_distrib]
id                 └────────────┘  └───────┘  └────────────┘  └────────────────┘
src     └─────────┘└────────────┘└┘└───────┘└┘└────────────┘└┘└────────────────┘└─
typ     └─────────┘└────────────┘└┘└───────┘└┘└────────────┘└┘└────────────────┘└─
doc     └─────────┘              └┘         └┘              └┘                  └─
txt     └─────────┘              └┘         └┘              └┘                  └─
par     └─────────┘              └┘         └┘              └┘                  └─
pid         └──┘└┘              └┘         └┘              └┘                  
st     └──────────────────────────────────────────────────────────────────────────
2068  
src  
typ  
doc  
txt  
par  
pid  
st   
2069  lemma sdiff_disjoint {s t : finset α} : disjoint (t \ s) s :=
id                               └────┘     └──────┘      
src                              └────┘      └──────┘    
typ                              └────┘     └──────┘      
doc                              └────┘      └──────┘
2070  disjoint_left.2 $ assume a ha, (mem_sdiff.1 ha).2
id   └───────────┘            └┘   └───────┘  └┘ 
src  └───────────┘                  └───────┘     
typ  └───────────┘            └┘   └───────┘  └┘ 
2071  
2072  lemma disjoint_sdiff {s t : finset α} : disjoint s (t \ s) :=
id                               └────┘     └──────┘     
src                              └────┘      └──────┘      
typ                              └────┘     └──────┘     
doc                              └────┘      └──────┘
2073  sdiff_disjoint.symm
id   └────────────┘└───┘
src  └────────────┘└───┘
typ  └────────────┘└───┘
2074  
2075  lemma disjoint_bind_left {ι : Type*} [decidable_eq ι]
id                                         └──────────┘ 
src                                        └──────────┘
typ                                        └──────────┘ 
2076    (s : finset ι) (f : ι → finset α) (t : finset α) :
id          └────┘           └────┘        └────┘ 
src         └────┘             └────┘         └────┘
typ         └────┘           └────┘        └────┘ 
doc         └────┘             └────┘         └────┘
2077    disjoint (s.bind f) t ↔ (∀i∈s, disjoint (f i) t) :=
id     └──────┘  └───┘          └──────┘     
src    └──────┘   └───┘              └──────┘
typ    └──────┘  └───┘          └──────┘     
doc    └──────┘   └───┘               └──────┘
2078  begin
st   └─────
2079    refine s.induction _ _,
id            └─────────┘
src    └─────┘└─────────┘└──┘
typ    └─────┘└─────────┘└──┘
doc    └─────┘           └──┘
txt    └─────┘           └──┘
par    └─────┘           └──┘
pid                     └──┘
st   ───────────────────────┘└─
2080    { simp only [forall_mem_empty_iff, bind_empty, disjoint_empty_left] },
id                  └──────────────────┘  └────────┘  └─────────────────┘
src      └─────────┘└──────────────────┘└┘└────────┘└┘└─────────────────┘└┘
typ      └─────────┘└──────────────────┘└┘└────────┘└┘└─────────────────┘└┘
doc      └─────────┘                    └┘          └┘                   └┘
txt      └─────────┘                    └┘          └┘                   └┘
par      └─────────┘                    └┘          └┘                   └┘
pid          └──┘└┘                    └┘          └┘                   
st   ───┘└────────────────────────────────────────────────────────────────┘└┘
2081    { assume i s his ih,
src      └───────────────┘
typ      └───────────────┘
doc      └───────────────┘
txt      └───────────────┘
par      └───────────────┘
pid      └───────────────┘
st   ────────────────────┘└─
2082      simp only [disjoint_union_left, bind_insert, his, forall_mem_insert, ih] }
id                  └─────────────────┘  └─────────┘  └─┘  └───────────────┘  └┘
src      └─────────┘└─────────────────┘└┘└─────────┘└┘   └┘└───────────────┘└┘  └┘
typ      └─────────┘└─────────────────┘└┘└─────────┘└┘└─┘└┘└───────────────┘└┘└┘└┘
doc      └─────────┘                   └┘           └┘   └┘                 └┘  └┘
txt      └─────────┘                   └┘           └┘   └┘                 └┘  └┘
par      └─────────┘                   └┘           └┘   └┘                 └┘  └┘
pid          └──┘└┘                   └┘           └┘   └┘                 └┘  
st   ────────────────────────────────────────────────────────────────────────────┘└─
2083  end
st   ──┘
2084  
2085  lemma disjoint_bind_right {ι : Type*} [decidable_eq ι]
id                                          └──────────┘ 
src                                         └──────────┘
typ                                         └──────────┘ 
2086    (s : finset α) (t : finset ι) (f : ι → finset α) :
id          └────┘        └────┘           └────┘ 
src         └────┘         └────┘             └────┘
typ         └────┘        └────┘           └────┘ 
doc         └────┘         └────┘             └────┘
2087    disjoint s (t.bind f) ↔ (∀i∈t, disjoint s (f i)) :=
id     └──────┘   └───┘         └──────┘    
src    └──────┘     └───┘            └──────┘
typ    └──────┘   └───┘         └──────┘    
doc    └──────┘     └───┘             └──────┘
2088  by simpa only [disjoint.comm] using disjoint_bind_left t f s
id                  └───────────┘        └────────────────┘   
src     └──────────┘└───────────┘└──────┘└────────────────┘   
typ     └──────────┘└───────────┘└──────┘└────────────────┘
doc     └──────────┘             └──────┘                     
txt     └──────────┘             └──────┘                     
par     └──────────┘             └──────┘                     
pid          └──┘└┘             └────┘                     
st     └──────────────────────────────────────────────────────────
2089  
src  
typ  
doc  
txt  
par  
pid  
st   
2090  @[simp] theorem card_disjoint_union {s t : finset α} (h : disjoint s t) :
id                                              └────┘        └──────┘  
src                                             └────┘         └──────┘
typ                                             └────┘        └──────┘  
doc    └──┘                                     └────┘         └──────┘
2091    card (s ∪ t) = card s + card t :=
id     └──┘       └──┘   └──┘ 
src    └──┘         └──┘    └──┘
typ    └──┘       └──┘   └──┘ 
doc    └──┘           └──┘     └──┘
2092  by rw [← card_union_add_card_inter, disjoint_iff_inter_eq_empty.1 h, card_empty, add_zero]
id            └───────────────────────┘  └─────────────────────────┘     └────────┘  └──────┘
src     └────┘└───────────────────────┘└┘└─────────────────────────┘└─┘ └┘└────────┘└┘└──────┘└─
typ     └────┘└───────────────────────┘└┘└─────────────────────────┘└─┘└┘└────────┘└┘└──────┘└─
doc     └────┘                         └┘                           └─┘ └┘          └┘        └─
txt     └────┘                         └┘                           └─┘ └┘          └┘        └─
par     └────┘                         └┘                           └─┘ └┘          └┘        └─
pid       └──┘                         └┘                           └─┘ └┘          └┘        
st     └──────────────────────────────┘└───────────────────────────────┘└──────────┘└────────┘
2093  
src  
typ  
doc  
txt  
par  
pid  
st   
2094  theorem card_sdiff {s t : finset α} (h : s ⊆ t) : card (t \ s) = card t - card s :=
id                             └────┘              └──┘       └──┘   └──┘ 
src                            └────┘                 └──┘         └──┘    └──┘
typ                            └────┘              └──┘       └──┘   └──┘ 
doc                            └────┘                  └──┘           └──┘     └──┘
2095  suffices card (t \ s) = card ((t \ s) ∪ s) - card s, by rwa sdiff_union_of_subset h at this,
id            └──┘       └──┘           └──┘          └───────────────────┘ 
src           └──┘         └──┘              └──┘       └──┘└───────────────────┘ └──────┘
typ           └──┘       └──┘           └──┘      └──┘└───────────────────┘└──────┘
doc           └──┘           └──┘                 └──┘       └──┘                      └──────┘
txt                                                          └──┘                      └──────┘
par                                                          └──┘                      └──────┘
pid                                                                                   └──────┘
st                                                          └──────────────────────────────────┘
2096  by rw [card_disjoint_union sdiff_disjoint, nat.add_sub_cancel]
id          └─────────────────┘ └────────────┘  └────────────────┘
src     └──┘└─────────────────┘└────────────┘└┘└────────────────┘└─
typ     └──┘└─────────────────┘└────────────┘└┘└────────────────┘└─
doc     └──┘                                 └┘                  └─
txt     └──┘                                 └┘                  └─
par     └──┘                                 └┘                  └─
pid       └┘                                 └┘                  
st     └─────────────────────────────────────┘└──────────────────┘
2097  
src  
typ  
doc  
txt  
par  
pid  
st   
2098  lemma disjoint_filter {s : finset α} {p q : α → Prop} [decidable_pred p] [decidable_pred q] :
id                              └────┘                    └────────────┘    └────────────┘ 
src                             └────┘                      └────────────┘     └────────────┘
typ                             └────┘                    └────────────┘    └────────────┘ 
doc                             └────┘
2099      disjoint (s.filter p) (s.filter q) ↔ (∀ x ∈ s, p x → ¬ q x) :=
id       └──────┘  └─────┘    └─────┘                  
src      └──────┘   └─────┘      └─────┘                     
typ      └──────┘  └─────┘    └─────┘                  
doc      └──────┘   └─────┘      └─────┘
2100  by split; simp [disjoint_left] {contextual := tt}
id                   └───────────┘                 └┘
src     └───┘  └────┘└───────────┘└┘ └────────────┘└┘└─
typ     └───┘  └────┘└───────────┘└┘ └────────────┘└┘└─
doc     └───┘  └────┘             └┘ └────────────┘  └─
txt     └───┘  └────┘             └┘ └────────────┘  └─
par     └───┘  └────┘             └┘ └────────────┘  └─
pid                              └────────────┘  
st     └───────────────────────────────────────────────
2101  
src  
typ  
doc  
txt  
par  
pid  
st   
2102  end disjoint
2103  
2104  theorem sort_sorted_lt [decidable_linear_order α] (s : finset α) :
id                           └────────────────────┘        └────┘ 
src                          └────────────────────┘         └────┘
typ                          └────────────────────┘        └────┘ 
doc                                                         └────┘
2105    list.sorted (<) (sort (≤) s) :=
id     └─────────┘     └──┘    
src    └─────────┘     └──┘ 
typ    └─────────┘     └──┘    
doc    └─────────┘      └──┘
2106  (sort_sorted _ _).imp₂ (@lt_of_le_of_ne _ _) (sort_nodup _ _)
id    └─────────┘     └──┘    └────────────┘       └────────┘
src   └─────────┘     └──┘    └────────────┘       └────────┘
typ   └─────────┘     └──┘    └────────────┘       └────────┘
2107  
2108  instance [has_repr α] : has_repr (finset α) := ⟨λ s, repr s.1⟩
id             └──────┘     └──────┘  └────┘           └──┘ 
src            └──────┘      └──────┘  └────┘             └──┘  
typ            └──────┘     └──────┘  └────┘           └──┘ 
doc                                    └────┘
2109  
2110  def attach_fin (s : finset ℕ) {n : ℕ} (h : ∀ m ∈ s, m < n) : finset (fin n) :=
id                       └────┘                            └────┘  └─┘ 
src                      └────┘                                └────┘  └─┘
typ                      └────┘                            └────┘  └─┘ 
doc                      └────┘                                   └────┘
2111  ⟨s.1.pmap (λ a ha, ⟨a, ha⟩) h, multiset.nodup_pmap (λ _ _ _ _, fin.mk.inj) s.2⟩
id     └──┘      └┘     └┘     └─────────────────┘         └────────┘  
src     └──┘                       └─────────────────┘             └────────┘   
typ    └──┘      └┘     └┘     └─────────────────┘         └────────┘  
doc      └──┘
2112  
2113  @[simp] lemma mem_attach_fin {n : ℕ} {s : finset ℕ} (h : ∀ m ∈ s, m < n) {a : fin n} :
id                                            └────┘                        └─┘ 
src                                           └────┘                            └─┘
typ                                           └────┘                        └─┘ 
doc    └──┘                                    └────┘
2114    a ∈ s.attach_fin h ↔ a.1 ∈ s :=
id       └─────────┘      
src        └─────────┘       
typ      └─────────┘      
2115  ⟨λ h, let ⟨b, hb₁, hb₂⟩ := multiset.mem_pmap.1 h in hb₂ ▸ hb₁,
id        └─┘     └─┘  └─┘     └───────────────┘          
src                             └───────────────┘           
typ       └─┘     └─┘  └─┘     └───────────────┘          
2116  λ h, multiset.mem_pmap.2 ⟨a.1, h, fin.eta _ _⟩⟩
id       └───────────────┘        └─────┘
src       └───────────────┘          └─────┘
typ      └───────────────┘        └─────┘
2117  
2118  @[simp] lemma card_attach_fin {n : ℕ} (s : finset ℕ) (h : ∀ m ∈ s, m < n) :
id                                             └────┘                 
src                                            └────┘                   
typ                                            └────┘                 
doc    └──┘                                     └────┘
2119    (s.attach_fin h).card = s.card := multiset.card_pmap _ _ _
id      └─────────┘  └──┘   └───┘    └────────────────┘
src      └─────────┘   └──┘    └───┘    └────────────────┘
typ     └─────────┘  └──┘   └───┘    └────────────────┘
doc                    └──┘     └───┘
2120  
2121  /-! ### choose -/
2122  section choose
2123  variables (p : α → Prop) [decidable_pred p] (l : finset α)
id                             └────────────┘         └────┘
src                            └────────────┘         └────┘
typ                            └────────────┘         └────┘
doc                                                   └────┘
2124  
2125  def choose_x (hp : (∃! a, a ∈ l ∧ p a)) : { a // a ∈ l ∧ p a } :=
id                       └┘                      
src                      └┘                            
typ                      └┘                      
2126  multiset.choose_x p l.val hp
id   └───────────────┘  └──┘ └┘
src  └───────────────┘    └──┘
typ  └───────────────┘  └──┘ └┘
2127  
2128  def choose (hp : ∃! a, a ∈ l ∧ p a) : α := choose_x p l hp
id                    └┘               └──────┘   └┘
src                   └┘                     └──────┘
typ                   └┘               └──────┘   └┘
2129  
2130  lemma choose_spec (hp : ∃! a, a ∈ l ∧ p a) : choose p l hp ∈ l ∧ p (choose p l hp) :=
id                           └┘           └────┘   └┘      └────┘   └┘
src                          └┘                └────┘               └────┘
typ                          └┘           └────┘   └┘      └────┘   └┘
2131  (choose_x p l hp).property
id    └──────┘   └┘ └──────┘
src   └──────┘        └──────┘
typ   └──────┘   └┘ └──────┘
2132  
2133  lemma choose_mem (hp : ∃! a, a ∈ l ∧ p a) : choose p l hp ∈ l := (choose_spec _ _ _).1
id                          └┘           └────┘   └┘       └─────────┘       
src                         └┘                └────┘               └─────────┘       
typ                         └┘           └────┘   └┘       └─────────┘       
2134  
2135  lemma choose_property (hp : ∃! a, a ∈ l ∧ p a) : p (choose p l hp) := (choose_spec _ _ _).2
id                               └┘             └────┘   └┘      └─────────┘       
src                              └┘                   └────┘             └─────────┘       
typ                              └┘             └────┘   └┘      └─────────┘       
2136  
2137  end choose
2138  
2139  theorem lt_wf {α} : well_founded (@has_lt.lt (finset α) _) :=
id                       └──────────┘   └───────┘  └────┘ 
src                      └──────────┘   └───────┘  └────┘
typ                      └──────────┘   └───────┘  └────┘ 
doc                                                └────┘
2140  have H : subrelation (@has_lt.lt (finset α) _)
id            └─────────┘   └───────┘  └────┘ 
src           └─────────┘   └───────┘  └────┘
typ           └─────────┘   └───────┘  └────┘ 
doc                                    └────┘
2141      (inv_image (<) card),
id        └───────┘    └──┘
src       └───────┘    └──┘
typ       └───────┘    └──┘
doc                     └──┘
2142    from λ x y hxy, card_lt_card hxy,
id              └─┘  └──────────┘ └─┘
src                    └──────────┘
typ             └─┘  └──────────┘ └─┘
2143  subrelation.wf H $ inv_image.wf _ $ nat.lt_wf
id   └────────────┘    └──────────┘     └───────┘
src  └────────────┘     └──────────┘     └───────┘
typ  └────────────┘    └──────────┘     └───────┘
2144  
2145  section decidable_linear_order
2146  
2147  variables {α} [decidable_linear_order α]
id                  └────────────────────┘
src                 └────────────────────┘
typ                 └────────────────────┘
2148  
2149  def min' (S : finset α) (H : S.nonempty) : α :=
id                 └────┘        └───────┘    
src                └────┘          └───────┘
typ                └────┘        └───────┘    
doc                └────┘          └───────┘
2150  @option.get _ S.min $
id    └────────┘   └──┘
src   └────────┘    └──┘
typ   └────────┘   └──┘
2151    let ⟨k, hk⟩ := H in
id     └─┘     └┘     
typ    └─┘     └┘     
2152    let ⟨b, hb⟩ := min_of_mem hk in by simp at hb; simp [hb]
id     └─┘            └────────┘                            └┘
src                   └────────┘          └────────┘  └────┘  └─
typ    └─┘            └────────┘          └────────┘  └────┘└┘└─
doc                                       └────────┘  └────┘  └─
txt                                       └────────┘  └────┘  └─
par                                       └────────┘  └────┘  └─
pid                                           └───┘        
st                                       └──────────────────────
2153  
src  
typ  
doc  
txt  
par  
pid  
st   
2154  def max' (S : finset α) (H : S.nonempty) : α :=
id                 └────┘        └───────┘    
src                └────┘          └───────┘
typ                └────┘        └───────┘    
doc                └────┘          └───────┘
2155  @option.get _ S.max $
id    └────────┘   └──┘
src   └────────┘    └──┘
typ   └────────┘   └──┘
2156    let ⟨k, hk⟩ := H in
id     └─┘     └┘     
typ    └─┘     └┘     
2157    let ⟨b, hb⟩ := max_of_mem hk in by simp at hb; simp [hb]
id     └─┘            └────────┘                            └┘
src                   └────────┘          └────────┘  └────┘  └─
typ    └─┘            └────────┘          └────────┘  └────┘└┘└─
doc                                       └────────┘  └────┘  └─
txt                                       └────────┘  └────┘  └─
par                                       └────────┘  └────┘  └─
pid                                           └───┘        
st                                       └──────────────────────
2158  
src  
typ  
doc  
txt  
par  
pid  
st   
2159  variables (S : finset α) (H : S.nonempty)
id                  └────┘          └───────┘
src                 └────┘          └───────┘
typ                 └────┘          └───────┘
doc                 └────┘          └───────┘
2160  
2161  theorem min'_mem : S.min' H ∈ S := mem_of_min $ by simp [min']
id                      └───┘       └────────┘            └──┘
src                      └───┘         └────────┘      └────┘└──┘└─
typ                     └───┘       └────────┘      └────┘└──┘└─
doc                                                     └────┘    └─
txt                                                     └────┘    └─
par                                                     └────┘    └─
pid                                                             
st                                                     └────────────
2162  
src  
typ  
doc  
txt  
par  
pid  
st   
2163  theorem min'_le (x) (H2 : x ∈ S) : S.min' H ≤ x := min_le_of_mem H2 $ option.get_mem _
id                                   └───┘       └───────────┘ └┘   └────────────┘
src                                     └───┘         └───────────┘      └────────────┘
typ                                  └───┘       └───────────┘ └┘   └────────────┘
2164  
2165  theorem le_min' (x) (H2 : ∀ y ∈ S, x ≤ y) : x ≤ S.min' H := H2 _ $ min'_mem _ _
id                                            └───┘     └┘     └──────┘
src                                                 └───┘             └──────┘
typ                                           └───┘     └┘     └──────┘
2166  
2167  theorem max'_mem : S.max' H ∈ S := mem_of_max $ by simp [max']
id                      └───┘       └────────┘            └──┘
src                      └───┘         └────────┘      └────┘└──┘└─
typ                     └───┘       └────────┘      └────┘└──┘└─
doc                                                     └────┘    └─
txt                                                     └────┘    └─
par                                                     └────┘    └─
pid                                                             
st                                                     └────────────
2168  
src  
typ  
doc  
txt  
par  
pid  
st   
2169  theorem le_max' (x) (H2 : x ∈ S) : x ≤ S.max' H := le_max_of_mem H2 $ option.get_mem _
id                                     └───┘     └───────────┘ └┘   └────────────┘
src                                        └───┘      └───────────┘      └────────────┘
typ                                    └───┘     └───────────┘ └┘   └────────────┘
2170  
2171  theorem max'_le (x) (H2 : ∀ y ∈ S, y ≤ x) : S.max' H ≤ x := H2 _ $ max'_mem _ _
id                                          └───┘       └┘     └──────┘
src                                              └───┘                └──────┘
typ                                         └───┘       └┘     └──────┘
2172  
2173  theorem min'_lt_max' {i j} (H1 : i ∈ S) (H2 : j ∈ S) (H3 : i ≠ j) : S.min' H < S.max' H :=
id                                                              └───┘   └───┘ 
src                                                                    └───┘     └───┘
typ                                                             └───┘   └───┘ 
2174  begin
st   └─────
2175    rcases lt_trichotomy i j with H4 | H4 | H4,
id            └───────────┘  
src    └─────┘└───────────┘  └────────────────┘
typ    └─────┘└───────────┘└────────────────┘
doc    └─────┘               └────────────────┘
txt    └─────┘               └────────────────┘
par    └─────┘               └────────────────┘
pid                         └────────────────┘
st   ───────────────────────────────────────────┘└─
2176    { have H5 := min'_le S H i H1,
id                  └─────┘    └┘
src      └─────────┘└─────┘   
typ      └─────────┘└─────┘└┘
doc      └─────────┘          
txt      └─────────┘          
par      └─────────┘          
pid      └─────┘└─┘          
st   ───┘└─────────────────────────┘└─
2177      have H6 := le_max' S H j H2,
id                  └─────┘    └┘
src      └─────────┘└─────┘   
typ      └─────────┘└─────┘└┘
doc      └─────────┘          
txt      └─────────┘          
par      └─────────┘          
pid      └─────┘└─┘          
st   ──────────────────────────────┘└─
2178      apply lt_of_le_of_lt H5,
id             └────────────┘ └┘
src      └────┘└────────────┘
typ      └────┘└────────────┘└┘
doc      └────┘              
txt      └────┘              
par      └────┘              
pid                         
st   ──────────────────────────┘└─
2179      apply lt_of_lt_of_le H4 H6 },
id             └────────────┘ └┘ └┘
src      └────┘└────────────┘    
typ      └────┘└────────────┘└┘└┘
doc      └────┘                  
txt      └────┘                  
par      └────┘                  
pid                             
st   ──────────────────────────────┘└┘
2180    { cc },
src      └─┘
typ      └─┘
doc      └─┘
txt      └─┘
par      └─┘
pid        
st   ───┘└─┘└┘
2181    { have H5 := min'_le S H j H2,
id                  └─────┘    └┘
src      └─────────┘└─────┘   
typ      └─────────┘└─────┘└┘
doc      └─────────┘          
txt      └─────────┘          
par      └─────────┘          
pid      └─────┘└─┘          
st   ──────────────────────────────┘└─
2182      have H6 := le_max' S H i H1,
id                  └─────┘    └┘
src      └─────────┘└─────┘   
typ      └─────────┘└─────┘└┘
doc      └─────────┘          
txt      └─────────┘          
par      └─────────┘          
pid      └─────┘└─┘          
st   ──────────────────────────────┘└─
2183      apply lt_of_le_of_lt H5,
id             └────────────┘ └┘
src      └────┘└────────────┘
typ      └────┘└────────────┘└┘
doc      └────┘              
txt      └────┘              
par      └────┘              
pid                         
st   ──────────────────────────┘└─
2184      apply lt_of_lt_of_le H4 H6 }
id             └────────────┘ └┘ └┘
src      └────┘└────────────┘    
typ      └────┘└────────────┘└┘└┘
doc      └────┘                  
txt      └────┘                  
par      └────┘                  
pid                             
st   ──────────────────────────────┘└─
2185  end
st   ──┘
2186  
2187  end decidable_linear_order
2188  
2189  /-! ### intervals -/
2190  /- Ico (a closed open interval) -/
2191  variables {n m l : ℕ}
id                      
src                     
typ                     
2192  
2193  /-- `Ico n m` is the set of natural numbers `n ≤ k < m`. -/
2194  def Ico (n m : ℕ) : finset ℕ := ⟨_, Ico.nodup n m⟩
id                      └────┘         └───────┘  
src                     └────┘         └───────┘
typ                     └────┘         └───────┘  
doc                      └────┘
2195  
2196  namespace Ico
2197  
2198  @[simp] theorem val (n m : ℕ) : (Ico n m).1 = multiset.Ico n m := rfl
id                                   └─┘      └──────────┘      └─┘
src                                  └─┘        └──────────┘        └─┘
typ                                  └─┘      └──────────┘      └─┘
doc    └──┘                           └─┘          └──────────┘
2199  
2200  @[simp] theorem to_finset (n m : ℕ) : (multiset.Ico n m).to_finset = Ico n m :=
id                                         └──────────┘   └───────┘   └─┘  
src                                        └──────────┘     └───────┘   └─┘
typ                                        └──────────┘   └───────┘   └─┘  
doc    └──┘                                 └──────────┘     └───────┘    └─┘
2201  (multiset.to_finset_eq _).symm
id    └───────────────────┘   └──┘
src   └───────────────────┘   └──┘
typ   └───────────────────┘   └──┘
2202  
2203  theorem image_add (n m k : ℕ) : (Ico n m).image ((+) k) = Ico (n + k) (m + k) :=
id                                   └─┘   └───┘         └─┘         
src                                  └─┘     └───┘          └─┘           
typ                                  └─┘   └───┘         └─┘         
doc                                   └─┘     └───┘            └─┘
2204  by simp [image, multiset.Ico.map_add]
id            └───┘  └──────────────────┘
src     └────┘└───┘└┘└──────────────────┘└─
typ     └────┘└───┘└┘└──────────────────┘└─
doc     └────┘└───┘└┘                    └─
txt     └────┘     └┘                    └─
par     └────┘     └┘                    └─
pid              └┘                    
st     └───────────────────────────────────
2205  
src  
typ  
doc  
txt  
par  
pid  
st   
2206  theorem image_sub (n m k : ℕ) (h : k ≤ n) : (Ico n m).image (λ x, x - k) = Ico (n - k) (m - k) :=
id                                            └─┘   └───┘            └─┘         
src                                             └─┘     └───┘               └─┘           
typ                                           └─┘   └───┘            └─┘         
doc                                               └─┘     └───┘                 └─┘
2207  begin
st   └─────
2208    dsimp [image],
id            └───┘
src    └─────┘└───┘
typ    └─────┘└───┘
doc    └─────┘└───┘
txt    └─────┘     
par    └─────┘     
pid              
st   ──────────────┘└─
2209    rw [multiset.Ico.map_sub _ _ _ h, ←multiset.to_finset_eq],
id         └──────────────────┘          └───────────────────┘
src    └──┘└──────────────────┘└─────┘ └─┘└───────────────────┘
typ    └──┘└──────────────────┘└─────┘└─┘└───────────────────┘
doc    └──┘                    └─────┘ └─┘                     
txt    └──┘                    └─────┘ └─┘                     
par    └──┘                    └─────┘ └─┘                     
pid      └┘                    └─────┘ └─┘                     
st   ─────────────────────────────────┘└──────────────────────┘└──
2210    refl,
src    └──┘
typ    └──┘
doc    └──┘
txt    └──┘
par    └──┘
st   ─────┘└─
2211  end
st   ──┘
2212  
2213  theorem zero_bot (n : ℕ) : Ico 0 n = range n :=
id                             └─┘     └───┘ 
src                            └─┘      └───┘
typ                            └─┘     └───┘ 
doc                             └─┘       └───┘
2214  eq_of_veq $ multiset.Ico.zero_bot _
id   └───────┘   └───────────────────┘
src  └───────┘   └───────────────────┘
typ  └───────┘   └───────────────────┘
2215  
2216  @[simp] theorem card (n m : ℕ) : (Ico n m).card = m - n :=
id                                    └─┘   └──┘     
src                                   └─┘     └──┘     
typ                                   └─┘   └──┘     
doc    └──┘                            └─┘     └──┘
2217  multiset.Ico.card _ _
id   └───────────────┘
src  └───────────────┘
typ  └───────────────┘
2218  
2219  @[simp] theorem mem {n m l : ℕ} : l ∈ Ico n m ↔ n ≤ l ∧ l < m :=
id                                      └─┘          
src                                      └─┘              
typ                                     └─┘          
doc    └──┘                                └─┘
2220  multiset.Ico.mem
id   └──────────────┘
src  └──────────────┘
typ  └──────────────┘
2221  
2222  theorem eq_empty_of_le {n m : ℕ} (h : m ≤ n) : Ico n m = ∅ :=
id                                              └─┘    
src                                               └─┘      
typ                                             └─┘    
doc                                                 └─┘
2223  eq_of_veq $ multiset.Ico.eq_zero_of_le h
id   └───────┘   └────────────────────────┘ 
src  └───────┘   └────────────────────────┘
typ  └───────┘   └────────────────────────┘ 
2224  
2225  @[simp] theorem self_eq_empty (n : ℕ) : Ico n n = ∅ :=
id                                          └─┘    
src                                         └─┘      
typ                                         └─┘    
doc    └──┘                                  └─┘
2226  eq_empty_of_le $ le_refl n
id   └────────────┘   └─────┘ 
src  └────────────┘   └─────┘
typ  └────────────┘   └─────┘ 
2227  
2228  @[simp] theorem eq_empty_iff {n m : ℕ} : Ico n m = ∅ ↔ m ≤ n :=
id                                           └─┘        
src                                          └─┘          
typ                                          └─┘        
doc    └──┘                                   └─┘
2229  iff.trans val_eq_zero.symm multiset.Ico.eq_zero_iff
id   └───────┘ └─────────┘└───┘ └──────────────────────┘
src  └───────┘ └─────────┘└───┘ └──────────────────────┘
typ  └───────┘ └─────────┘└───┘ └──────────────────────┘
2230  
2231  theorem subset_iff {m₁ n₁ m₂ n₂ : ℕ} (hmn : m₁ < n₁) :
id                                              └┘  └┘
src                                                
typ                                             └┘  └┘
2232    Ico m₁ n₁ ⊆ Ico m₂ n₂ ↔ (m₂ ≤ m₁ ∧ n₁ ≤ n₂) :=
id     └─┘ └┘ └┘  └─┘ └┘ └┘   └┘  └┘  └┘  └┘
src    └─┘        └─┘                    
typ    └─┘ └┘ └┘  └─┘ └┘ └┘   └┘  └┘  └┘  └┘
doc    └─┘         └─┘
2233  begin
st   └─────
2234    simp only [subset_iff, mem],
id                └────────┘  └─┘
src    └─────────┘└────────┘└┘└─┘
typ    └─────────┘└────────┘└┘└─┘
doc    └─────────┘          └┘   
txt    └─────────┘          └┘   
par    └─────────┘          └┘   
pid        └──┘└┘          └┘   
st   ────────────────────────────┘└─
2235    refine ⟨λ h, ⟨_, _⟩, _⟩,
src    └─────┘  └──┘ └───────┘
typ    └─────┘  └──┘ └───────┘
doc    └─────┘  └──┘ └───────┘
txt    └─────┘  └──┘ └───────┘
par    └─────┘  └──┘ └───────┘
pid            └──┘ └───────┘
st   ────────────────────────┘└─
2236    { exact (h ⟨le_refl _, hmn⟩).1 },
id                └─────┘    └─┘
src      └────┘   └─────┘└──┘   └───┘
typ      └────┘  └─────┘└──┘└─┘└───┘
doc      └────┘          └──┘   └───┘
txt      └────┘          └──┘   └───┘
par      └────┘          └──┘   └───┘
pid                     └──┘   └┘└─┘
st   ───┘└───────────────────────────┘└┘
2237    { refine le_of_pred_lt (@h (pred n₁) ⟨le_pred_of_lt hmn, pred_lt _⟩).2,
id              └───────────┘     └──┘ └┘   └───────────┘ └─┘  └─────┘
src      └─────┘└───────────┘    └──┘  └┘ └───────────┘   └┘└─────┘└────┘
typ      └─────┘└───────────┘   └──┘└┘└┘ └───────────┘└─┘└┘└─────┘└────┘
doc      └─────┘                       └┘                 └┘       └────┘
txt      └─────┘                       └┘                 └┘       └────┘
par      └─────┘                       └┘                 └┘       └────┘
pid                                   └┘                 └┘       └──┘└┘
st   ───┘└──────────────────────────────────────────────────────────────────┘└─
2238      exact ne_of_gt (lt_of_le_of_lt (nat.zero_le m₁) hmn) },
id             └──────┘  └────────────┘  └─────────┘ └┘  └─┘
src      └────┘└──────┘ └────────────┘ └─────────┘  └┘   └┘
typ      └────┘└──────┘ └────────────┘ └─────────┘└┘└┘└─┘└┘
doc      └────┘                                     └┘   └┘
txt      └────┘                                     └┘   └┘
par      └────┘                                     └┘   └┘
pid                                                └┘   
st   ────────────────────────────────────────────────────────┘└┘
2239    { rintros ⟨hm, hn⟩ k ⟨hmk, hkn⟩,
src      └───────────────────────────┘
typ      └───────────────────────────┘
doc      └───────────────────────────┘
txt      └───────────────────────────┘
par      └───────────────────────────┘
pid             └────────────────────┘
st   ────────────────────────────────┘└─
2240      exact ⟨le_trans hm hmk, lt_of_lt_of_le hkn hn⟩ }
id              └──────┘ └┘ └─┘  └────────────┘ └─┘ └┘
src      └────┘ └──────┘     └┘└────────────┘     └┘
typ      └────┘ └──────┘└┘└─┘└┘└────────────┘└─┘└┘└┘
doc      └────┘              └┘                   └┘
txt      └────┘              └┘                   └┘
par      └────┘              └┘                   └┘
pid                         └┘                   
st   ──────────────────────────────────────────────────┘└─
2241  end
st   ──┘
2242  
2243  protected theorem subset {m₁ n₁ m₂ n₂ : ℕ} (hmm : m₂ ≤ m₁) (hnn : n₁ ≤ n₂) :
id                                                    └┘  └┘         └┘  └┘
src                                                                     
typ                                                   └┘  └┘         └┘  └┘
2244    Ico m₁ n₁ ⊆ Ico m₂ n₂ :=
id     └─┘ └┘ └┘  └─┘ └┘ └┘
src    └─┘        └─┘
typ    └─┘ └┘ └┘  └─┘ └┘ └┘
doc    └─┘         └─┘
2245  begin
st   └─────
2246    simp only [finset.subset_iff, Ico.mem],
id                └───────────────┘  └─────┘
src    └─────────┘└───────────────┘└┘└─────┘
typ    └─────────┘└───────────────┘└┘└─────┘
doc    └─────────┘                 └┘       
txt    └─────────┘                 └┘       
par    └─────────┘                 └┘       
pid        └──┘└┘                 └┘       
st   ───────────────────────────────────────┘└─
2247    assume x hx,
src    └─────────┘
typ    └─────────┘
doc    └─────────┘
txt    └─────────┘
par    └─────────┘
pid    └─────────┘
st   ────────────┘└─
2248    exact ⟨le_trans hmm hx.1, lt_of_lt_of_le hx.2 hnn⟩
id            └──────┘ └─┘       └────────────┘ └┘   └─┘
src    └────┘ └──────┘     └──┘└────────────┘  └─┘   └┘
typ    └────┘ └──────┘└─┘  └──┘└────────────┘└┘└─┘└─┘└┘
doc    └────┘              └──┘                └─┘   └┘
txt    └────┘              └──┘                └─┘   └┘
par    └────┘              └──┘                └─┘   └┘
pid                       └──┘                └─┘   
st   ────────────────────────────────────────────────────┘
2249  end
st   └─┘
2250  
2251  lemma union_consecutive {n m l : ℕ} (hnm : n ≤ m) (hml : m ≤ l) :
id                                                          
src                                                           
typ                                                         
2252    Ico n m ∪ Ico m l = Ico n l :=
id     └─┘    └─┘    └─┘  
src    └─┘      └─┘      └─┘
typ    └─┘    └─┘    └─┘  
doc    └─┘       └─┘       └─┘
2253  by rw [← to_finset, ← to_finset, ← multiset.to_finset_add,
id            └───────┘    └───────┘    └────────────────────┘
src     └────┘└───────┘└──┘└───────┘└──┘└────────────────────┘└─
typ     └────┘└───────┘└──┘└───────┘└──┘└────────────────────┘└─
doc     └────┘         └──┘         └──┘                      └─
txt     └────┘         └──┘         └──┘                      └─
par     └────┘         └──┘         └──┘                      └─
pid       └──┘         └──┘         └──┘                      └─
st     └──────────────┘└───────────┘└────────────────────────┘└─
2254    multiset.Ico.add_consecutive hnm hml, to_finset]
id     └──────────────────────────┘ └─┘ └─┘  └───────┘
src  ─┘└──────────────────────────┘      └┘└───────┘└─
typ  ─┘└──────────────────────────┘└─┘└─┘└┘└───────┘└─
doc  ─┘                                  └┘         └─
txt  ─┘                                  └┘         └─
par  ─┘                                  └┘         └─
pid  ─┘                                  └┘         
st   ─────────────────────────────────────┘└─────────┘
2255  
src  
typ  
doc  
txt  
par  
pid  
st   
2256  @[simp] lemma inter_consecutive (n m l : ℕ) : Ico n m ∩ Ico m l = ∅ :=
id                                                └─┘    └─┘    
src                                               └─┘      └─┘      
typ                                               └─┘    └─┘    
doc    └──┘                                        └─┘       └─┘
2257  begin
st   └─────
2258    rw [← to_finset, ← to_finset, ← multiset.to_finset_inter, multiset.Ico.inter_consecutive],
id           └───────┘    └───────┘    └──────────────────────┘  └────────────────────────────┘
src    └────┘└───────┘└──┘└───────┘└──┘└──────────────────────┘└┘└────────────────────────────┘
typ    └────┘└───────┘└──┘└───────┘└──┘└──────────────────────┘└┘└────────────────────────────┘
doc    └────┘         └──┘         └──┘                        └┘                              
txt    └────┘         └──┘         └──┘                        └┘                              
par    └────┘         └──┘         └──┘                        └┘                              
pid      └──┘         └──┘         └──┘                        └┘                              
st   ────────────────┘└───────────┘└──────────────────────────┘└──────────────────────────────┘└──
2259    simp,
src    └──┘
typ    └──┘
doc    └──┘
txt    └──┘
par    └──┘
st   ─────┘└─
2260  end
st   ──┘
2261  
2262  lemma disjoint_consecutive (n m l : ℕ) : disjoint (Ico n m) (Ico m l) :=
id                                           └──────┘  └─┘     └─┘  
src                                          └──────┘  └─┘       └─┘
typ                                          └──────┘  └─┘     └─┘  
doc                                           └──────┘  └─┘       └─┘
2263  le_of_eq $ inter_consecutive n m l
id   └──────┘   └───────────────┘   
src  └──────┘   └───────────────┘
typ  └──────┘   └───────────────┘   
2264  
2265  @[simp] theorem succ_singleton (n : ℕ) : Ico n (n+1) = {n} :=
id                                           └─┘       
src                                          └─┘         
typ                                          └─┘       
doc    └──┘                                   └─┘
2266  eq_of_veq $ multiset.Ico.succ_singleton
id   └───────┘   └─────────────────────────┘
src  └───────┘   └─────────────────────────┘
typ  └───────┘   └─────────────────────────┘
2267  
2268  theorem succ_top {n m : ℕ} (h : n ≤ m) : Ico n (m + 1) = insert m (Ico n m) :=
id                                        └─┘         └────┘   └─┘  
src                                         └─┘           └────┘    └─┘
typ                                       └─┘         └────┘   └─┘  
doc                                           └─┘                       └─┘
2269  by rw [← to_finset, multiset.Ico.succ_top h, multiset.to_finset_cons, to_finset]
id            └───────┘  └───────────────────┘   └─────────────────────┘  └───────┘
src     └────┘└───────┘└┘└───────────────────┘ └┘└─────────────────────┘└┘└───────┘└─
typ     └────┘└───────┘└┘└───────────────────┘└┘└─────────────────────┘└┘└───────┘└─
doc     └────┘         └┘                      └┘                       └┘         └─
txt     └────┘         └┘                      └┘                       └┘         └─
par     └────┘         └┘                      └┘                       └┘         └─
pid       └──┘         └┘                      └┘                       └┘         
st     └──────────────┘└───────────────────────┘└───────────────────────┘└─────────┘
2270  
src  
typ  
doc  
txt  
par  
pid  
st   
2271  theorem succ_top' {n m : ℕ} (h : n < m) : Ico n m = insert (m - 1) (Ico n (m - 1)) :=
id                                         └─┘    └────┘        └─┘    
src                                          └─┘      └────┘         └─┘      
typ                                        └─┘    └────┘        └─┘    
doc                                            └─┘                       └─┘
2272  begin
st   └─────
2273    have w : m = m - 1 + 1 := (nat.sub_add_cancel (nat.one_le_of_lt h)).symm,
id                            └────────────────┘  └──────────────┘ 
src    └───────┘  └─┘└────┘ └────────────────┘ └──────────────┘ └─────┘
typ    └───────┘ └─┘└────┘ └────────────────┘ └──────────────┘└─────┘
doc    └───────┘    └─┘ └────┘                                     └─────┘
txt    └───────┘    └─┘ └────┘                                     └─────┘
par    └───────┘    └─┘ └────┘                                     └─────┘
pid    └────┘└─┘    └─┘ └───┘                                     └────┘
st   ─────────────────────────────────────────────────────────────────────────┘└─
2274    conv { to_lhs, rw w },
id                       
src    └─────┘└────┘└┘└─┘ 
typ    └─────┘└────┘└┘└─┘
txt    └─────┘└────┘└┘└─┘ 
par    └─────┘└────┘└┘└─┘ 
pid        └───────────┘ └┘
st   ───────┘└─────┘└─────┘└┘
2275    rw succ_top,
id        └──────┘
src    └─┘└──────┘
typ    └─┘└──────┘
doc    └─┘
txt    └─┘
par    └─┘
pid      
st   ────────────┘└─
2276    exact nat.le_pred_of_lt h
id           └───────────────┘ 
src    └────┘└───────────────┘ 
typ    └────┘└───────────────┘
doc    └────┘                  
txt    └────┘                  
par    └────┘                  
pid                           
st   ───────────────────────────┘
2277  end
st   └─┘
2278  
2279  theorem insert_succ_bot {n m : ℕ} (h : n < m) : insert n (Ico (n + 1) m) = Ico n m :=
id                                               └────┘   └─┘          └─┘  
src                                                └────┘    └─┘            └─┘
typ                                              └────┘   └─┘          └─┘  
doc                                                            └─┘              └─┘
2280  by rw [eq_comm, ← to_finset, multiset.Ico.eq_cons h, multiset.to_finset_cons, to_finset]
id          └─────┘    └───────┘  └──────────────────┘   └─────────────────────┘  └───────┘
src     └──┘└─────┘└──┘└───────┘└┘└──────────────────┘ └┘└─────────────────────┘└┘└───────┘└─
typ     └──┘└─────┘└──┘└───────┘└┘└──────────────────┘└┘└─────────────────────┘└┘└───────┘└─
doc     └──┘       └──┘         └┘                     └┘                       └┘         └─
txt     └──┘       └──┘         └┘                     └┘                       └┘         └─
par     └──┘       └──┘         └┘                     └┘                       └┘         └─
pid       └┘       └──┘         └┘                     └┘                       └┘         
st     └──────────┘└───────────┘└──────────────────────┘└───────────────────────┘└─────────┘
2281  
src  
typ  
doc  
txt  
par  
pid  
st   
2282  @[simp] theorem pred_singleton {m : ℕ} (h : 0 < m) : Ico (m - 1) m = {m - 1} :=
id                                                     └─┘          
src                                                     └─┘             
typ                                                    └─┘          
doc    └──┘                                               └─┘
2283  eq_of_veq $ multiset.Ico.pred_singleton h
id   └───────┘   └─────────────────────────┘ 
src  └───────┘   └─────────────────────────┘
typ  └───────┘   └─────────────────────────┘ 
2284  
2285  @[simp] theorem not_mem_top {n m : ℕ} : m ∉ Ico n m :=
id                                            └─┘  
src                                            └─┘
typ                                           └─┘  
doc    └──┘                                      └─┘
2286  multiset.Ico.not_mem_top
id   └──────────────────────┘
src  └──────────────────────┘
typ  └──────────────────────┘
2287  
2288  lemma filter_lt_of_top_le {n m l : ℕ} (hml : m ≤ l) : (Ico n m).filter (λ x, x < l) = Ico n m :=
id                                                      └─┘   └────┘            └─┘  
src                                                       └─┘     └────┘               └─┘
typ                                                     └─┘   └────┘            └─┘  
doc                                                         └─┘     └────┘                 └─┘
2289  eq_of_veq $ multiset.Ico.filter_lt_of_top_le hml
id   └───────┘   └──────────────────────────────┘ └─┘
src  └───────┘   └──────────────────────────────┘
typ  └───────┘   └──────────────────────────────┘ └─┘
2290  
2291  lemma filter_lt_of_le_bot {n m l : ℕ} (hln : l ≤ n) : (Ico n m).filter (λ x, x < l) = ∅ :=
id                                                      └─┘   └────┘            
src                                                       └─┘     └────┘               
typ                                                     └─┘   └────┘            
doc                                                         └─┘     └────┘
2292  eq_of_veq $ multiset.Ico.filter_lt_of_le_bot hln
id   └───────┘   └──────────────────────────────┘ └─┘
src  └───────┘   └──────────────────────────────┘
typ  └───────┘   └──────────────────────────────┘ └─┘
2293  
2294  lemma filter_lt_of_ge {n m l : ℕ} (hlm : l ≤ m) : (Ico n m).filter (λ x, x < l) = Ico n l :=
id                                                  └─┘   └────┘            └─┘  
src                                                   └─┘     └────┘               └─┘
typ                                                 └─┘   └────┘            └─┘  
doc                                                     └─┘     └────┘                 └─┘
2295  eq_of_veq $ multiset.Ico.filter_lt_of_ge hlm
id   └───────┘   └──────────────────────────┘ └─┘
src  └───────┘   └──────────────────────────┘
typ  └───────┘   └──────────────────────────┘ └─┘
2296  
2297  @[simp] lemma filter_lt (n m l : ℕ) : (Ico n m).filter (λ x, x < l) = Ico n (min m l) :=
id                                         └─┘   └────┘            └─┘   └─┘  
src                                        └─┘     └────┘               └─┘    └─┘
typ                                        └─┘   └────┘            └─┘   └─┘  
doc    └──┘                                 └─┘     └────┘                 └─┘
2298  eq_of_veq $ multiset.Ico.filter_lt n m l
id   └───────┘   └────────────────────┘   
src  └───────┘   └────────────────────┘
typ  └───────┘   └────────────────────┘   
2299  
2300  lemma filter_le_of_le_bot {n m l : ℕ} (hln : l ≤ n) : (Ico n m).filter (λ x, l ≤ x) = Ico n m :=
id                                                      └─┘   └────┘            └─┘  
src                                                       └─┘     └────┘               └─┘
typ                                                     └─┘   └────┘            └─┘  
doc                                                         └─┘     └────┘                 └─┘
2301  eq_of_veq $ multiset.Ico.filter_le_of_le_bot hln
id   └───────┘   └──────────────────────────────┘ └─┘
src  └───────┘   └──────────────────────────────┘
typ  └───────┘   └──────────────────────────────┘ └─┘
2302  
2303  lemma filter_le_of_top_le {n m l : ℕ} (hml : m ≤ l) : (Ico n m).filter (λ x, l ≤ x) = ∅ :=
id                                                      └─┘   └────┘            
src                                                       └─┘     └────┘               
typ                                                     └─┘   └────┘            
doc                                                         └─┘     └────┘
2304  eq_of_veq $ multiset.Ico.filter_le_of_top_le hml
id   └───────┘   └──────────────────────────────┘ └─┘
src  └───────┘   └──────────────────────────────┘
typ  └───────┘   └──────────────────────────────┘ └─┘
2305  
2306  lemma filter_le_of_le {n m l : ℕ} (hnl : n ≤ l) : (Ico n m).filter (λ x, l ≤ x) = Ico l m :=
id                                                  └─┘   └────┘            └─┘  
src                                                   └─┘     └────┘               └─┘
typ                                                 └─┘   └────┘            └─┘  
doc                                                     └─┘     └────┘                 └─┘
2307  eq_of_veq $ multiset.Ico.filter_le_of_le hnl
id   └───────┘   └──────────────────────────┘ └─┘
src  └───────┘   └──────────────────────────┘
typ  └───────┘   └──────────────────────────┘ └─┘
2308  
2309  @[simp] lemma filter_le (n m l : ℕ) : (Ico n m).filter (λ x, l ≤ x) = Ico (max n l) m :=
id                                         └─┘   └────┘            └─┘  └─┘    
src                                        └─┘     └────┘               └─┘  └─┘
typ                                        └─┘   └────┘            └─┘  └─┘    
doc    └──┘                                 └─┘     └────┘                 └─┘
2310  eq_of_veq $ multiset.Ico.filter_le n m l
id   └───────┘   └────────────────────┘   
src  └───────┘   └────────────────────┘
typ  └───────┘   └────────────────────┘   
2311  
2312  @[simp] lemma diff_left (l n m : ℕ) : (Ico n m) \ (Ico n l) = Ico (max n l) m :=
id                                         └─┘      └─┘     └─┘  └─┘    
src                                        └─┘        └─┘       └─┘  └─┘
typ                                        └─┘      └─┘     └─┘  └─┘    
doc    └──┘                                 └─┘         └─┘        └─┘
2313  by ext k; by_cases n ≤ k; simp [h, and_comm]
id                                  └──────┘
src     └───┘  └───────┘    └────┘ └┘└──────┘└─
typ     └───┘  └───────┘  └────┘└┘└──────┘└─
doc     └───┘  └───────┘     └────┘ └┘        └─
txt     └───┘  └───────┘     └────┘ └┘        └─
par     └───┘  └───────┘     └────┘ └┘        └─
pid        └┘                    └┘        
st     └──────────────────────────────────────────
2314  
src  
typ  
doc  
txt  
par  
pid  
st   
2315  @[simp] lemma diff_right (l n m : ℕ) : (Ico n m) \ (Ico l m) = Ico n (min m l) :=
id                                          └─┘      └─┘     └─┘   └─┘  
src                                         └─┘        └─┘       └─┘    └─┘
typ                                         └─┘      └─┘     └─┘   └─┘  
doc    └──┘                                  └─┘         └─┘        └─┘
2316  have ∀k, (k < m ∧ (l ≤ k → m ≤ k)) ↔ (k < m ∧ k < l) :=
id                                   
src                                           
typ                                  
2317    assume k, and_congr_right $ assume hk, by rw [← not_imp_not]; simp [hk],
id              └─────────────┘          └┘           └─────────┘         └┘
src              └─────────────┘                 └────┘└─────────┘  └────┘  
typ             └─────────────┘          └┘     └────┘└─────────┘  └────┘└┘
doc                                              └────┘             └────┘  
txt                                              └────┘             └────┘  
par                                              └────┘             └────┘  
pid                                                └──┘                   
st                                              └────────────────┘└─────────┘
2318  by ext k; by_cases n ≤ k; simp [h, this]
id                                  └──┘
src     └───┘  └───────┘    └────┘ └┘    └─
typ     └───┘  └───────┘  └────┘└┘└──┘└─
doc     └───┘  └───────┘     └────┘ └┘    └─
txt     └───┘  └───────┘     └────┘ └┘    └─
par     └───┘  └───────┘     └────┘ └┘    └─
pid        └┘                    └┘    
st     └──────────────────────────────────────
2319  
src  
typ  
doc  
txt  
par  
pid  
st   
2320  end Ico
2321  
2322  -- TODO We don't yet attempt to reproduce the entire interface for `Ico` for `Ico_ℤ`.
2323  
2324  /-- `Ico_ℤ l u` is the set of integers `l ≤ k < u`. -/
2325  def Ico_ℤ (l u : ℤ) : finset ℤ :=
id                        └────┘ 
src                       └────┘ 
typ                       └────┘ 
doc                        └────┘
2326  (finset.range (u - l).to_nat).map
id    └──────────┘     └────┘  └─┘
src   └──────────┘       └────┘  └─┘
typ   └──────────┘     └────┘  └─┘
doc   └──────────┘
2327    { to_fun := λ n, n + l,
id                       
src                       
typ                      
2328      inj := λ n m h, by simpa using h }
id                                   
src                         └──────────┘ 
typ                      └──────────┘
doc                         └──────────┘ 
txt                         └──────────┘ 
par                         └──────────┘ 
pid                              └────┘ 
st                         └─────────────┘
2329  
2330  namespace Ico_ℤ
2331  
2332  @[simp] lemma mem {n m l : ℤ} : l ∈ Ico_ℤ n m ↔ n ≤ l ∧ l < m :=
id                                    └───┘          
src                                    └───┘              
typ                                   └───┘          
doc    └──┘                              └───┘
2333  begin
st   └─────
2334    dsimp [Ico_ℤ],
id            └───┘
src    └─────┘└───┘
typ    └─────┘└───┘
doc    └─────┘└───┘
txt    └─────┘     
par    └─────┘     
pid              
st   ──────────────┘└─
2335    simp only [int.lt_to_nat, exists_prop, mem_range, add_comm, function.embedding.coe_fn_mk, mem_map],
id                └───────────┘  └─────────┘  └───────┘  └──────┘  └──────────────────────────┘  └─────┘
src    └─────────┘└───────────┘└┘└─────────┘└┘└───────┘└┘└──────┘└┘└──────────────────────────┘└┘└─────┘
typ    └─────────┘└───────────┘└┘└─────────┘└┘└───────┘└┘└──────┘└┘└──────────────────────────┘└┘└─────┘
doc    └─────────┘             └┘           └┘         └┘        └┘                            └┘       
txt    └─────────┘             └┘           └┘         └┘        └┘                            └┘       
par    └─────────┘             └┘           └┘         └┘        └┘                            └┘       
pid        └──┘└┘             └┘           └┘         └┘        └┘                            └┘       
st   ───────────────────────────────────────────────────────────────────────────────────────────────────┘└─
2336    split,
src    └───┘
typ    └───┘
doc    └───┘
txt    └───┘
par    └───┘
st   ──────┘└─
2337    { rintro ⟨a, ⟨h, rfl⟩⟩,
src      └──────────────────┘
typ      └──────────────────┘
doc      └──────────────────┘
txt      └──────────────────┘
par      └──────────────────┘
pid            └────────────┘
st   ───┘└──────────────────┘└─
2338      exact ⟨int.le.intro rfl, lt_sub_iff_add_lt'.mp h⟩ },
id              └──────────┘ └─┘  └───────────────────┘ 
src      └────┘ └──────────┘└─┘└┘└───────────────────┘ └┘
typ      └────┘ └──────────┘└─┘└┘└───────────────────┘└┘
doc      └────┘                └┘                      └┘
txt      └────┘                └┘                      └┘
par      └────┘                └┘                      └┘
pid                           └┘                      
st   ─────────────────────────────────────────────────────┘└┘
2339    { rintro ⟨h₁, h₂⟩,
src      └─────────────┘
typ      └─────────────┘
doc      └─────────────┘
txt      └─────────────┘
par      └─────────────┘
pid            └───────┘
st   ──────────────────┘└─
2340      use (l - n).to_nat,
id              
src      └──┘   └──────┘
typ      └──┘ └──────┘
doc      └──┘    └──────┘
txt      └──┘    └──────┘
par      └──┘    └──────┘
pid             └─────┘
st   ─────────────────────┘└─
2341      split; simp [h₁, h₂], }
id                    └┘  └┘
src      └───┘  └────┘  └┘  
typ      └───┘  └────┘└┘└┘└┘
doc      └───┘  └────┘  └┘  
txt      └───┘  └────┘  └┘  
par      └───┘  └────┘  └┘  
pid                   └┘  
st   ───────────────────────┘└───
2342  end
st   ──┘
2343  
2344  end Ico_ℤ
2345  
2346  end finset
2347  
2348  namespace multiset
2349  
2350  lemma count_sup [decidable_eq β] (s : finset α) (f : α → multiset β) (b : β) :
id                    └──────────┘        └────┘           └──────┘        
src                   └──────────┘         └────┘             └──────┘
typ                   └──────────┘        └────┘           └──────┘        
doc                                        └────┘             └──────┘
2351    count b (s.sup f) = s.sup (λa, count b (f a)) :=
id     └───┘   └──┘    └──┘     └───┘    
src    └───┘     └──┘      └──┘      └───┘
typ    └───┘   └──┘    └──┘     └───┘    
doc    └───┘     └──┘       └──┘      └───┘
2352  begin
st   └─────
2353    letI := classical.dec_eq α,
id             └──────────────┘ 
src    └──────┘└──────────────┘
typ    └──────┘└──────────────┘
doc    └──────┘                
txt    └──────┘                
par    └──────┘                
pid        └─┘                
st   ───────────────────────────┘└─
2354    refine s.induction _ _,
id            └─────────┘
src    └─────┘└─────────┘└──┘
typ    └─────┘└─────────┘└──┘
doc    └─────┘           └──┘
txt    └─────┘           └──┘
par    └─────┘           └──┘
pid                     └──┘
st   ───────────────────────┘└─
2355    { exact count_zero _ },
id             └────────┘
src      └────┘└────────┘└─┘
typ      └────┘└────────┘└─┘
doc      └────┘          └─┘
txt      └────┘          └─┘
par      └────┘          └─┘
pid                     └┘
st   ───┘└─────────────────┘└┘
2356    { assume i s his ih,
src      └───────────────┘
typ      └───────────────┘
doc      └───────────────┘
txt      └───────────────┘
par      └───────────────┘
pid      └───────────────┘
st   ────────────────────┘└─
2357      rw [finset.sup_insert, sup_eq_union, count_union, finset.sup_insert, ih],
id           └───────────────┘  └──────────┘  └─────────┘  └───────────────┘  └┘
src      └──┘└───────────────┘└┘└──────────┘└┘└─────────┘└┘└───────────────┘└┘  
typ      └──┘└───────────────┘└┘└──────────┘└┘└─────────┘└┘└───────────────┘└┘└┘
doc      └──┘                 └┘            └┘           └┘                 └┘  
txt      └──┘                 └┘            └┘           └┘                 └┘  
par      └──┘                 └┘            └┘           └┘                 └┘  
pid        └┘                 └┘            └┘           └┘                 └┘  
st   ────────────────────────┘└────────────┘└───────────┘└─────────────────┘└──┘└──
2358      refl }
src      └───┘
typ      └───┘
doc      └───┘
txt      └───┘
par      └───┘
pid          
st   ────────┘└─
2359  end
st   ──┘
2360  
2361  end multiset
2362  
2363  namespace list
2364  variable [decidable_eq α]
id             └──────────┘
src            └──────────┘
typ            └──────────┘
2365  
2366  theorem to_finset_card_of_nodup {l : list α} (h : l.nodup) : l.to_finset.card = l.length :=
id                                        └──┘        └────┘    └────────┘└───┘  └─────┘
src                                       └──┘          └────┘     └────────┘└───┘   └─────┘
typ                                       └──┘        └────┘    └────────┘└───┘  └─────┘
doc                                                     └────┘     └────────┘└───┘
2367  congr_arg card $ (@multiset.erase_dup_eq_self α _ l).2 h
id   └───────┘ └──┘     └────────────────────────┘       
src  └───────┘ └──┘     └────────────────────────┘       
typ  └───────┘ └──┘     └────────────────────────┘       
doc            └──┘
2368  
2369  end list
2370  
2371  namespace lattice
2372  variables {ι : Sort*} [complete_lattice α] [decidable_eq ι]
id                          └──────────────┘     └──────────┘
src                         └──────────────┘     └──────────┘
typ                         └──────────────┘     └──────────┘
doc                         └──────────────┘
2373  
2374  lemma supr_eq_supr_finset (s : ι → α) : (⨆i, s i) = (⨆t:finset (plift ι), ⨆i∈t, s (plift.down i)) :=
id                                                  └────┘  └───┘       └────────┘ 
src                                                      └────┘  └───┘           └────────┘
typ                                                 └────┘  └───┘       └────────┘ 
doc                                                       └────┘  └───┘       
2375  le_antisymm
id   └─────────┘
src  └─────────┘
typ  └─────────┘
2376    (supr_le $ assume b, le_supr_of_le {plift.up b} $ le_supr_of_le (plift.up b) $ le_supr_of_le
id      └─────┘            └───────────┘ └──────┘     └───────────┘  └──────┘     └───────────┘
src     └─────┘             └───────────┘ └──────┘      └───────────┘  └──────┘      └───────────┘
typ     └─────┘            └───────────┘ └──────┘     └───────────┘  └──────┘     └───────────┘
2377      (by simp) $ le_refl _)
id                   └─────┘
src          └──┘    └─────┘
typ          └──┘    └─────┘
doc          └──┘
txt          └──┘
par          └──┘
st          └───┘
2378    (supr_le $ assume t, supr_le $ assume b, supr_le $ assume hb, le_supr _ _)
id      └─────┘            └─────┘            └─────┘          └┘  └─────┘
src     └─────┘             └─────┘             └─────┘              └─────┘
typ     └─────┘            └─────┘            └─────┘          └┘  └─────┘
2379  
2380  lemma infi_eq_infi_finset (s : ι → α) : (⨅i, s i) = (⨅t:finset (plift ι), ⨅i∈t, s (plift.down i)) :=
id                                                  └────┘  └───┘       └────────┘ 
src                                                      └────┘  └───┘           └────────┘
typ                                                 └────┘  └───┘       └────────┘ 
doc                                                       └────┘  └───┘       
2381  le_antisymm
id   └─────────┘
src  └─────────┘
typ  └─────────┘
2382    (le_infi $ assume t, le_infi $ assume b, le_infi $ assume hb, infi_le _ _)
id      └─────┘            └─────┘            └─────┘          └┘  └─────┘
src     └─────┘             └─────┘             └─────┘              └─────┘
typ     └─────┘            └─────┘            └─────┘          └┘  └─────┘
2383    (le_infi $ assume b, infi_le_of_le {plift.up b} $ infi_le_of_le (plift.up b) $ infi_le_of_le
id      └─────┘            └───────────┘ └──────┘     └───────────┘  └──────┘     └───────────┘
src     └─────┘             └───────────┘ └──────┘      └───────────┘  └──────┘      └───────────┘
typ     └─────┘            └───────────┘ └──────┘     └───────────┘  └──────┘     └───────────┘
2384      (by simp) $ le_refl _)
id                   └─────┘
src          └──┘    └─────┘
typ          └──┘    └─────┘
doc          └──┘
txt          └──┘
par          └──┘
st          └───┘
2385  
2386  end lattice
2387  
2388  namespace set
2389  variables {ι : Sort*} [decidable_eq ι]
id                          └──────────┘
src                         └──────────┘
typ                         └──────────┘
2390  
2391  lemma Union_eq_Union_finset (s : ι → set α) :
id                                       └─┘ 
src                                       └─┘
typ                                      └─┘ 
2392    (⋃i, s i) = (⋃t:finset (plift ι), ⋃i∈t, s (plift.down i)) :=
id              └────┘  └───┘       └────────┘ 
src                └────┘  └───┘           └────────┘
typ             └────┘  └───┘       └────────┘ 
doc                 └────┘  └───┘       
2393  lattice.supr_eq_supr_finset s
id   └─────────────────────────┘ 
src  └─────────────────────────┘
typ  └─────────────────────────┘ 
2394  
2395  lemma Inter_eq_Inter_finset (s : ι → set α) :
id                                       └─┘ 
src                                       └─┘
typ                                      └─┘ 
2396    (⋂i, s i) = (⋂t:finset (plift ι), ⋂i∈t, s (plift.down i)) :=
id              └────┘  └───┘       └────────┘ 
src                └────┘  └───┘           └────────┘
typ             └────┘  └───┘       └────────┘ 
doc                 └────┘  └───┘       
2397  lattice.infi_eq_infi_finset s
id   └─────────────────────────┘ 
src  └─────────────────────────┘
typ  └─────────────────────────┘ 
2398  
2399  end set
2400  
2401  namespace finset
2402  
2403  namespace nat
2404  
2405  /-- The antidiagonal of a natural number `n` is
2406      the finset of pairs `(i,j)` such that `i+j = n`. -/
2407  def antidiagonal (n : ℕ) : finset (ℕ × ℕ) :=
id                             └────┘    
src                            └────┘    
typ                            └────┘    
doc                             └────┘
2408  (multiset.nat.antidiagonal n).to_finset
id    └───────────────────────┘  └───────┘
src   └───────────────────────┘   └───────┘
typ   └───────────────────────┘  └───────┘
doc   └───────────────────────┘   └───────┘
2409  
2410  /-- A pair (i,j) is contained in the antidiagonal of `n` if and only if `i+j=n`. -/
2411  @[simp] lemma mem_antidiagonal {n : ℕ} {x : ℕ × ℕ} :
id                                                
src                                               
typ                                               
doc    └──┘
2412    x ∈ antidiagonal n ↔ x.1 + x.2 = n :=
id       └──────────┘         
src       └──────────┘           
typ      └──────────┘         
doc        └──────────┘
2413  by rw [antidiagonal, multiset.mem_to_finset, multiset.nat.mem_antidiagonal]
id          └──────────┘  └────────────────────┘  └───────────────────────────┘
src     └──┘└──────────┘└┘└────────────────────┘└┘└───────────────────────────┘└─
typ     └──┘└──────────┘└┘└────────────────────┘└┘└───────────────────────────┘└─
doc     └──┘└──────────┘└┘                      └┘└───────────────────────────┘└─
txt     └──┘            └┘                      └┘                             └─
par     └──┘            └┘                      └┘                             └─
pid       └┘            └┘                      └┘                             
st     └───────────────┘└──────────────────────┘└─────────────────────────────┘
2414  
src  
typ  
doc  
txt  
par  
pid  
st   
2415  /-- The cardinality of the antidiagonal of `n` is `n+1`. -/
2416  @[simp] lemma card_antidiagonal (n : ℕ) : (antidiagonal n).card = n+1 :=
id                                             └──────────┘  └──┘   
src                                            └──────────┘   └──┘    
typ                                            └──────────┘  └──┘   
doc    └──┘                                     └──────────┘   └──┘
2417  by simpa using list.to_finset_card_of_nodup (list.nat.nodup_antidiagonal n)
id                  └──────────────────────────┘  └─────────────────────────┘ 
src     └──────────┘└──────────────────────────┘ └─────────────────────────┘ └─
typ     └──────────┘└──────────────────────────┘ └─────────────────────────┘└─
doc     └──────────┘                             └─────────────────────────┘ └─
txt     └──────────┘                                                         └─
par     └──────────┘                                                         └─
pid          └────┘                                                         
st     └─────────────────────────────────────────────────────────────────────────
2418  
src  
typ  
doc  
txt  
par  
pid  
st   
2419  /-- The antidiagonal of `0` is the list `[(0,0)]` -/
2420  @[simp] lemma antidiagonal_zero : antidiagonal 0 = {(0, 0)} :=
id                                     └──────────┘    
src                                    └──────────┘    
typ                                    └──────────┘    
doc    └──┘                            └──────────┘
2421  by { rw [antidiagonal, multiset.nat.antidiagonal_zero], refl }
id            └──────────┘  └────────────────────────────┘
src       └──┘└──────────┘└┘└────────────────────────────┘  └───┘
typ       └──┘└──────────┘└┘└────────────────────────────┘  └───┘
doc       └──┘└──────────┘└┘└────────────────────────────┘  └───┘
txt       └──┘            └┘                                └───┘
par       └──┘            └┘                                └───┘
pid         └┘            └┘                                    
st     └─────────────────┘└──────────────────────────────┘└──────┘└┘
2422  
2423  end nat
2424  
2425  end finset
2426  
2427  namespace finset
2428  
2429  /-! ### bUnion -/
2430  
2431  variables [decidable_eq α]
id              └──────────┘
src             └──────────┘
typ             └──────────┘
2432  
2433  @[simp] theorem bUnion_singleton (a : α) (s : α → set β) : (⋃ x ∈ ({a} : finset α), s x) = s a :=
id                                                   └─┘               └────┘        
src                                                    └─┘                  └────┘         
typ                                                  └─┘               └────┘        
doc    └──┘                                                                  └────┘   
2434  supr_singleton
id   └────────────┘
src  └────────────┘
typ  └────────────┘
2435  
2436  @[simp] theorem supr_union {α} [complete_lattice α] {β} [decidable_eq β] {f : β → α} {s t : finset β} :
id                                   └──────────────┘        └──────────┘                    └────┘ 
src                                  └──────────────┘         └──────────┘                       └────┘
typ                                  └──────────────┘        └──────────┘                    └────┘ 
doc    └──┘                          └──────────────┘                                            └────┘
2437    (⨆ x ∈ s ∪ t, f x) = (⨆x∈s, f x) ⊔ (⨆x∈t, f x) :=
id                            
src                                    
typ                           
doc                                       
2438  calc (⨆ x ∈ s ∪ t, f x) = (⨆ x, (⨆h : x∈s, f x) ⊔ (⨆h : x∈t, f x)) :
id                                         
src                                                  
typ                                        
doc                                                      
2439    congr_arg _ $ funext $ λ x, by { convert supr_or, rw finset.mem_union, rw finset.mem_union, refl, refl }
id     └───────┘     └────┘                    └─────┘     └──────────────┘     └──────────────┘
src    └───────┘     └────┘             └──────┘└─────┘  └─┘└──────────────┘  └─┘└──────────────┘  └──┘  └───┘
typ    └───────┘     └────┘            └──────┘└─────┘  └─┘└──────────────┘  └─┘└──────────────┘  └──┘  └───┘
doc                                     └──────┘         └─┘                  └─┘                  └──┘  └───┘
txt                                     └──────┘         └─┘                  └─┘                  └──┘  └───┘
par                                     └──────┘         └─┘                  └─┘                  └──┘  └───┘
pid                                                                                                       
st                                   └────────────────┘└───────────────────┘└───────────────────┘└────┘└─────┘└┘
2440                      ... = (⨆x∈s, f x) ⊔ (⨆x∈t, f x) : supr_sup_eq
id                                            └─────────┘
src                                                   └─────────┘
typ                                           └─────────┘
doc                                            
2441  
2442  lemma bUnion_union (s t : finset α) (u : α → set β) :
id                             └────┘           └─┘ 
src                            └────┘             └─┘
typ                            └────┘           └─┘ 
doc                            └────┘
2443    (⋃ x ∈ s ∪ t, u x) = (⋃ x ∈ s, u x) ∪ (⋃ x ∈ t, u x) :=
id                                  
src                                          
typ                                 
doc                                             
2444  supr_union
id   └────────┘
src  └────────┘
typ  └────────┘
2445  
2446  @[simp] lemma bUnion_insert (a : α) (s : finset α) (t : α → set β) :
id                                           └────┘           └─┘ 
src                                           └────┘             └─┘
typ                                          └────┘           └─┘ 
doc    └──┘                                   └────┘
2447    (⋃ x ∈ insert a s, t x) = t a ∪ (⋃ x ∈ s, t x) :=
id          └────┘                 
src          └────┘                       
typ         └────┘                 
doc                                         
2448  begin rw insert_eq, simp only [bUnion_union, finset.bUnion_singleton] end
id            └───────┘             └──────────┘  └─────────────────────┘
src        └─┘└───────┘  └─────────┘└──────────┘└┘└─────────────────────┘└┘
typ        └─┘└───────┘  └─────────┘└──────────┘└┘└─────────────────────┘└┘
doc        └─┘           └─────────┘            └┘                       └┘
txt        └─┘           └─────────┘            └┘                       └┘
par        └─┘           └─────────┘            └┘                       └┘
pid                         └──┘└┘            └┘                       
st   └────────────────┘└──────────────────────────────────────────────────┘└─┘
2449  
2450  end finset